Module: kamailio Branch: master Commit: 308b7a2f7b6a7c50e05a2c83537f85b95f979c32 URL: https://github.com/kamailio/kamailio/commit/308b7a2f7b6a7c50e05a2c83537f85b9...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: 2019-08-16T10:11:21+02:00
core: tcp - new core parameter tcp_accept_unique
- if set to 1, do an extra check when a new connection is created to be sure the is no overlapping with another connection on local ip/port and remote ip/port - recently some tcp/ip router/balancers can do port sharing, but that can create troubles for routing of the requests with the current tcp routing implementation (e.g., using the wrong connection in such group) - default is set to 0
---
Modified: src/core/cfg.lex Modified: src/core/cfg.y Modified: src/core/globals.h Modified: src/core/tcp_main.c
---
Diff: https://github.com/kamailio/kamailio/commit/308b7a2f7b6a7c50e05a2c83537f85b9... Patch: https://github.com/kamailio/kamailio/commit/308b7a2f7b6a7c50e05a2c83537f85b9...
---
diff --git a/src/core/cfg.lex b/src/core/cfg.lex index dd1b935d8f..20a8fd94ef 100644 --- a/src/core/cfg.lex +++ b/src/core/cfg.lex @@ -375,6 +375,7 @@ MHOMED mhomed DISABLE_TCP "disable_tcp" TCP_CHILDREN "tcp_children" TCP_ACCEPT_ALIASES "tcp_accept_aliases" +TCP_ACCEPT_UNIQUE "tcp_accept_unique" TCP_SEND_TIMEOUT "tcp_send_timeout" TCP_CONNECT_TIMEOUT "tcp_connect_timeout" TCP_CON_LIFETIME "tcp_connection_lifetime" @@ -814,6 +815,8 @@ IMPORTFILE "import_file" <INITIAL>{TCP_CHILDREN} { count(); yylval.strval=yytext; return TCP_CHILDREN; } <INITIAL>{TCP_ACCEPT_ALIASES} { count(); yylval.strval=yytext; return TCP_ACCEPT_ALIASES; } +<INITIAL>{TCP_ACCEPT_UNIQUE} { count(); yylval.strval=yytext; + return TCP_ACCEPT_UNIQUE; } <INITIAL>{TCP_SEND_TIMEOUT} { count(); yylval.strval=yytext; return TCP_SEND_TIMEOUT; } <INITIAL>{TCP_CONNECT_TIMEOUT} { count(); yylval.strval=yytext; diff --git a/src/core/cfg.y b/src/core/cfg.y index 4c7dcd1307..3adff2429b 100644 --- a/src/core/cfg.y +++ b/src/core/cfg.y @@ -406,6 +406,7 @@ extern char *default_routename; %token MHOMED %token DISABLE_TCP %token TCP_ACCEPT_ALIASES +%token TCP_ACCEPT_UNIQUE %token TCP_CHILDREN %token TCP_CONNECT_TIMEOUT %token TCP_SEND_TIMEOUT @@ -994,6 +995,14 @@ assign_stm: #endif } | TCP_ACCEPT_ALIASES EQUAL error { yyerror("boolean value expected"); } + | TCP_ACCEPT_UNIQUE EQUAL NUMBER { + #ifdef USE_TCP + tcp_accept_unique=$3; + #else + warn("tcp support not compiled in"); + #endif + } + | TCP_ACCEPT_UNIQUE EQUAL error { yyerror("number expected"); } | TCP_CHILDREN EQUAL NUMBER { #ifdef USE_TCP tcp_cfg_children_no=$3; diff --git a/src/core/globals.h b/src/core/globals.h index 3790058075..78a8e5aadc 100644 --- a/src/core/globals.h +++ b/src/core/globals.h @@ -93,6 +93,7 @@ extern int socket_workers; #ifdef USE_TCP extern int tcp_main_pid; extern int tcp_cfg_children_no; +extern int tcp_accept_unique; extern int tcp_children_no; extern int tcp_disable; extern enum poll_types tcp_poll_method; diff --git a/src/core/tcp_main.c b/src/core/tcp_main.c index 54288e908f..7ecaf47eb6 100644 --- a/src/core/tcp_main.c +++ b/src/core/tcp_main.c @@ -158,6 +158,7 @@ enum poll_types tcp_poll_method=0; /* by default choose the best method */ int tcp_main_max_fd_no=0; int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS; int tls_max_connections=DEFAULT_TLS_MAX_CONNECTIONS; +int tcp_accept_unique=0;
static union sockaddr_union tcp_source_ipv4_addr; /* saved bind/srv v4 addr. */ static union sockaddr_union* tcp_source_ipv4=0; @@ -1655,6 +1656,24 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port, }
+/** + * find if a tcp connection exits by id or remote+local address/port + * - return: 1 if found; 0 if not found + */ +int tcpconn_exists(int conn_id, ip_addr_t* peer_ip, int peer_port, + ip_addr_t* local_ip, int local_port) +{ + tcp_connection_t* c; + + TCPCONN_LOCK; + c=_tcpconn_find(conn_id, peer_ip, peer_port, local_ip, local_port); + TCPCONN_UNLOCK; + if (c) { + return 1; + } + return 0; + +}
/* _tcpconn_find with locks and timeout * local_addr contains the desired local ip:port. If null any local address @@ -4245,6 +4264,15 @@ static inline int handle_new_connect(struct socket_info* si) /* add socket to list */ tcpconn=tcpconn_new(new_sock, &su, dst_su, si, si->proto, S_CONN_ACCEPT); if (likely(tcpconn)){ + if(tcp_accept_unique) { + if(tcpconn_exists(0, &tcpconn->rcv.dst_ip, tcpconn->rcv.dst_port, + &tcpconn->rcv.src_ip, tcpconn->rcv.src_port)) { + LM_ERR("duplicated connection by local and remote addresses\n"); + _tcpconn_free(tcpconn); + tcp_safe_close(new_sock); + return 1; /* success, because the accept was succesfull */ + } + } tcpconn->flags|=F_CONN_PASSIVE; #ifdef TCP_PASS_NEW_CONNECTION_ON_DATA atomic_set(&tcpconn->refcnt, 1); /* safe, not yet available to the