Browse code

core/tcp/tls: added tls_max_connections global parameter

- set a limit to active tls connections
- its management is done in tcp code, as tls is encryption layer over
tcp
- tls connections are still counted as tcp connections, thus this limit
cannot exceed tcp_max_connections
- default value 2048
- core.tcp_options lists also the tls connections number

Daniel-Constantin Mierla authored on 13/12/2011 22:01:48
Showing 9 changed files
... ...
@@ -414,6 +414,7 @@ TCP_CONNECT_TIMEOUT	"tcp_connect_timeout"
414 414
 TCP_CON_LIFETIME	"tcp_connection_lifetime"
415 415
 TCP_POLL_METHOD		"tcp_poll_method"
416 416
 TCP_MAX_CONNECTIONS	"tcp_max_connections"
417
+TLS_MAX_CONNECTIONS	"tls_max_connections"
417 418
 TCP_NO_CONNECT		"tcp_no_connect"
418 419
 TCP_SOURCE_IPV4		"tcp_source_ipv4"
419 420
 TCP_SOURCE_IPV6		"tcp_source_ipv6"
... ...
@@ -805,6 +806,8 @@ IMPORTFILE      "import_file"
805 805
 									return TCP_POLL_METHOD; }
806 806
 <INITIAL>{TCP_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
807 807
 									return TCP_MAX_CONNECTIONS; }
808
+<INITIAL>{TLS_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
809
+									return TLS_MAX_CONNECTIONS; }
808 810
 <INITIAL>{TCP_NO_CONNECT}		{ count(); yylval.strval=yytext;
809 811
 									return TCP_NO_CONNECT; }
810 812
 <INITIAL>{TCP_SOURCE_IPV4}		{ count(); yylval.strval=yytext;
... ...
@@ -472,6 +472,7 @@ extern char *finame;
472 472
 %token TCP_CON_LIFETIME
473 473
 %token TCP_POLL_METHOD
474 474
 %token TCP_MAX_CONNECTIONS
475
+%token TLS_MAX_CONNECTIONS
475 476
 %token TCP_NO_CONNECT
476 477
 %token TCP_SOURCE_IPV4
477 478
 %token TCP_SOURCE_IPV6
... ...
@@ -1063,6 +1064,14 @@ assign_stm:
1063 1063
 		#endif
1064 1064
 	}
1065 1065
 	| TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
1066
+	| TLS_MAX_CONNECTIONS EQUAL NUMBER {
1067
+		#ifdef USE_TLS
1068
+			tls_max_connections=$3;
1069
+		#else
1070
+			warn("tls support not compiled in");
1071
+		#endif
1072
+	}
1073
+	| TLS_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
1066 1074
 	| TCP_NO_CONNECT EQUAL NUMBER {
1067 1075
 		#ifdef USE_TCP
1068 1076
 			tcp_default_cfg.no_connect=$3;
... ...
@@ -677,10 +677,12 @@ static void core_tcpinfo(rpc_t* rpc, void* c)
677 677
 	if (!tcp_disable){
678 678
 		tcp_get_info(&ti);
679 679
 		rpc->add(c, "{", &handle);
680
-		rpc->struct_add(handle, "dddd",
680
+		rpc->struct_add(handle, "dddddd",
681 681
 			"readers", ti.tcp_readers,
682 682
 			"max_connections", ti.tcp_max_connections,
683
+			"max_tls_connections", ti.tls_max_connections,
683 684
 			"opened_connections", ti.tcp_connections_no,
685
+			"opened_tls_connections", ti.tls_connections_no,
684 686
 			"write_queued_bytes", ti.tcp_write_queued
685 687
 		);
686 688
 	}else{
... ...
@@ -707,11 +709,12 @@ static void core_tcp_options(rpc_t* rpc, void* c)
707 707
 	if (!tcp_disable){
708 708
 		tcp_options_get(&t);
709 709
 		rpc->add(c, "{", &handle);
710
-		rpc->struct_add(handle, "dddddddddddddddddddddd",
710
+		rpc->struct_add(handle, "ddddddddddddddddddddddd",
711 711
 			"connect_timeout", t.connect_timeout_s,
712 712
 			"send_timeout",  TICKS_TO_S(t.send_timeout),
713 713
 			"connection_lifetime",  TICKS_TO_S(t.con_lifetime),
714 714
 			"max_connections(soft)", t.max_connections,
715
+			"max_tls_connections(soft)", t.max_tls_connections,
715 716
 			"no_connect",	t.no_connect,
716 717
 			"fd_cache",		t.fd_cache,
717 718
 			"async",		t.async,
... ...
@@ -93,7 +93,8 @@ extern int tcp_main_pid;
93 93
 extern int tcp_children_no;
94 94
 extern int tcp_disable;
95 95
 extern enum poll_types tcp_poll_method;
96
-extern int tcp_max_connections; /* maximum connections, hard limit */
96
+extern int tcp_max_connections; /* maximum tcp connections, hard limit */
97
+extern int tls_max_connections; /* maximum tls connections, hard limit */
97 98
 #endif
98 99
 #ifdef USE_TLS
99 100
 extern int tls_disable;
... ...
@@ -34,7 +34,9 @@
34 34
 struct tcp_gen_info{
35 35
 	int tcp_readers;
36 36
 	int tcp_max_connections; /* startup connection limit, cannot be exceeded*/
37
-	int tcp_connections_no; /* crt. number */
37
+	int tls_max_connections; /* startup tls limit, cannot exceed tcp limit*/
38
+	int tcp_connections_no; /* crt. connections number */
39
+	int tls_connections_no; /* crt. tls connections number */
38 40
 	int tcp_write_queued; /* total bytes queued for write, 0 if no
39 41
 							 write queued support is enabled */
40 42
 };
... ...
@@ -37,7 +37,9 @@
37 37
 									   timeout */
38 38
 #define DEFAULT_TCP_CONNECT_TIMEOUT 10 /* if a connect doesn't complete in this
39 39
 										  time, timeout */
40
-#define DEFAULT_TCP_MAX_CONNECTIONS 2048 /* maximum connections */
40
+#define DEFAULT_TCP_MAX_CONNECTIONS 2048 /* maximum tcp connections */
41
+
42
+#define DEFAULT_TLS_MAX_CONNECTIONS 2048 /* maximum tls connections */
41 43
 
42 44
 #define DEFAULT_TCP_BUF_SIZE	4096  /* buffer size used for reads */
43 45
 
... ...
@@ -250,6 +250,7 @@ static int is_tcp_main=0;
250 250
 enum poll_types tcp_poll_method=0; /* by default choose the best method */
251 251
 int tcp_main_max_fd_no=0;
252 252
 int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS;
253
+int tls_max_connections=DEFAULT_TLS_MAX_CONNECTIONS;
253 254
 
254 255
 static union sockaddr_union tcp_source_ipv4_addr; /* saved bind/srv v4 addr. */
255 256
 static union sockaddr_union* tcp_source_ipv4=0;
... ...
@@ -258,7 +259,8 @@ static union sockaddr_union tcp_source_ipv6_addr; /* saved bind/src v6 addr. */
258 258
 static union sockaddr_union* tcp_source_ipv6=0;
259 259
 #endif
260 260
 
261
-static int* tcp_connections_no=0; /* current open connections */
261
+static int* tcp_connections_no=0; /* current tcp (+tls) open connections */
262
+static int* tls_connections_no=0; /* current tls open connections */
262 263
 
263 264
 /* connection hash table (after ip&port) , includes also aliases */
264 265
 struct tcp_conn_alias** tcpconn_aliases_hash=0;
... ...
@@ -1261,6 +1263,16 @@ struct tcp_connection* tcpconn_connect( union sockaddr_union* server,
1261 1261
 					cfg_get(tcp, tcp_cfg, max_connections));
1262 1262
 		goto error;
1263 1263
 	}
1264
+	if (unlikely(type==PROTO_TLS)) {
1265
+		if (*tls_connections_no >= cfg_get(tcp, tcp_cfg, max_tls_connections)){
1266
+			LM_ERR("ERROR: maximum number of tls connections"
1267
+						" exceeded (%d/%d)\n",
1268
+						*tls_connections_no,
1269
+						cfg_get(tcp, tcp_cfg, max_tls_connections));
1270
+			goto error;
1271
+		}
1272
+	}
1273
+
1264 1274
 	s=tcp_do_connect(server, from, type,  send_flags, &my_name, &si, &state);
1265 1275
 	if (s==-1){
1266 1276
 		LOG(L_ERR, "ERROR: tcp_do_connect %s: failed (%d) %s\n",
... ...
@@ -1849,6 +1861,17 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1849 1849
 							cfg_get(tcp, tcp_cfg, max_connections));
1850 1850
 				return -1;
1851 1851
 			}
1852
+			if (unlikely(dst->proto==PROTO_TLS)) {
1853
+				if (unlikely(*tls_connections_no >=
1854
+							cfg_get(tcp, tcp_cfg, max_tls_connections))){
1855
+					LM_ERR("tcp_send %s: maximum number of"
1856
+							" tls connections exceeded (%d/%d)\n",
1857
+							su2a(&dst->to, sizeof(dst->to)),
1858
+							*tls_connections_no,
1859
+							cfg_get(tcp, tcp_cfg, max_tls_connections));
1860
+					return -1;
1861
+				}
1862
+			}
1852 1863
 			c=tcpconn_new(-1, &dst->to, from, 0, dst->proto,
1853 1864
 							S_CONN_CONNECT);
1854 1865
 			if (unlikely(c==0)){
... ...
@@ -2992,6 +3015,8 @@ inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
2992 2992
 			tcpconn_close_main_fd(tcpconn);
2993 2993
 			tcpconn->flags|=F_CONN_FD_CLOSED;
2994 2994
 			(*tcp_connections_no)--;
2995
+			if (unlikely(tcpconn->type==PROTO_TLS))
2996
+				(*tls_connections_no)--;
2995 2997
 		}
2996 2998
 		_tcpconn_free(tcpconn); /* destroys also the wbuf_q if still present*/
2997 2999
 }
... ...
@@ -3038,6 +3063,8 @@ inline static int tcpconn_put_destroy(struct tcp_connection* tcpconn)
3038 3038
 		tcpconn_close_main_fd(tcpconn);
3039 3039
 		tcpconn->flags|=F_CONN_FD_CLOSED;
3040 3040
 		(*tcp_connections_no)--;
3041
+		if (unlikely(tcpconn->type==PROTO_TLS))
3042
+				(*tls_connections_no)--;
3041 3043
 	}
3042 3044
 	/* all the flags / ops on the tcpconn must be done prior to decrementing
3043 3045
 	 * the refcnt. and at least a membar_write_atomic_op() mem. barrier or
... ...
@@ -3656,6 +3683,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
3656 3656
 				break;
3657 3657
 			}
3658 3658
 			(*tcp_connections_no)++;
3659
+			if (unlikely(tcpconn->type==PROTO_TLS))
3660
+				(*tls_connections_no)++;
3659 3661
 			tcpconn->s=fd;
3660 3662
 			/* add tcpconn to the list*/
3661 3663
 			tcpconn_add(tcpconn);
... ...
@@ -3787,6 +3816,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
3787 3787
 				break;
3788 3788
 			}
3789 3789
 			(*tcp_connections_no)++;
3790
+			if (unlikely(tcpconn->type==PROTO_TLS))
3791
+				(*tls_connections_no)++;
3790 3792
 			tcpconn->s=fd;
3791 3793
 			/* update the timeout*/
3792 3794
 			t=get_ticks_raw();
... ...
@@ -3974,12 +4005,24 @@ static inline int handle_new_connect(struct socket_info* si)
3974 3974
 		TCP_STATS_LOCAL_REJECT();
3975 3975
 		return 1; /* success, because the accept was succesfull */
3976 3976
 	}
3977
+	if (unlikely(si->proto==PROTO_TLS)) {
3978
+		if (unlikely(*tls_connections_no>=cfg_get(tcp, tcp_cfg, max_tls_connections))){
3979
+			LM_ERR("maximum number of tls connections exceeded: %d/%d\n",
3980
+					*tls_connections_no,
3981
+					cfg_get(tcp, tcp_cfg, max_tls_connections));
3982
+			tcp_safe_close(new_sock);
3983
+			TCP_STATS_LOCAL_REJECT();
3984
+			return 1; /* success, because the accept was succesfull */
3985
+		}
3986
+	}
3977 3987
 	if (unlikely(init_sock_opt_accept(new_sock)<0)){
3978 3988
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
3979 3989
 		tcp_safe_close(new_sock);
3980 3990
 		return 1; /* success, because the accept was succesfull */
3981 3991
 	}
3982 3992
 	(*tcp_connections_no)++;
3993
+	if (unlikely(si->proto==PROTO_TLS))
3994
+		(*tls_connections_no)++;
3983 3995
 	/* stats for established connections are incremented after
3984 3996
 	   the first received or sent packet.
3985 3997
 	   Alternatively they could be incremented here for accepted
... ...
@@ -4044,6 +4087,8 @@ static inline int handle_new_connect(struct socket_info* si)
4044 4044
 				"closing socket\n");
4045 4045
 		tcp_safe_close(new_sock);
4046 4046
 		(*tcp_connections_no)--;
4047
+		if (unlikely(si->proto==PROTO_TLS))
4048
+			(*tls_connections_no)--;
4047 4049
 	}
4048 4050
 	return 1; /* accept() was succesfull */
4049 4051
 }
... ...
@@ -4428,6 +4473,8 @@ static inline void tcpconn_destroy_all()
4428 4428
 					tcp_safe_close(fd);
4429 4429
 				}
4430 4430
 				(*tcp_connections_no)--;
4431
+				if (unlikely(c->type==PROTO_TLS))
4432
+					(*tls_connections_no)--;
4431 4433
 			c=next;
4432 4434
 		}
4433 4435
 	}
... ...
@@ -4621,6 +4668,10 @@ void destroy_tcp()
4621 4621
 			shm_free(tcp_connections_no);
4622 4622
 			tcp_connections_no=0;
4623 4623
 		}
4624
+		if (tls_connections_no){
4625
+			shm_free(tls_connections_no);
4626
+			tls_connections_no=0;
4627
+		}
4624 4628
 #ifdef TCP_ASYNC
4625 4629
 		if (tcp_total_wq){
4626 4630
 			shm_free(tcp_total_wq);
... ...
@@ -4677,6 +4728,12 @@ int init_tcp()
4677 4677
 		goto error;
4678 4678
 	}
4679 4679
 	*tcp_connections_no=0;
4680
+	tls_connections_no=shm_malloc(sizeof(int));
4681
+	if (tls_connections_no==0){
4682
+		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
4683
+		goto error;
4684
+	}
4685
+	*tls_connections_no=0;
4680 4686
 	if (INIT_TCP_STATS()!=0) goto error;
4681 4687
 	connection_id=shm_malloc(sizeof(int));
4682 4688
 	if (connection_id==0){
... ...
@@ -4838,7 +4895,9 @@ void tcp_get_info(struct tcp_gen_info *ti)
4838 4838
 {
4839 4839
 	ti->tcp_readers=tcp_children_no;
4840 4840
 	ti->tcp_max_connections=tcp_max_connections;
4841
+	ti->tls_max_connections=tls_max_connections;
4841 4842
 	ti->tcp_connections_no=*tcp_connections_no;
4843
+	ti->tls_connections_no=*tls_connections_no;
4842 4844
 #ifdef TCP_ASYNC
4843 4845
 	ti->tcp_write_queued=*tcp_total_wq;
4844 4846
 #else
... ...
@@ -69,7 +69,10 @@ static cfg_def_t tcp_cfg_def[] = {
69 69
 		"connection lifetime (in seconds)"},
70 70
 	{ "max_connections", CFG_VAR_INT | CFG_ATOMIC, 0, (1U<<31)-1,
71 71
 													       fix_max_conns,    0,
72
-		"maximum connection number, soft limit"},
72
+		"maximum tcp connections number, soft limit"},
73
+	{ "max_tls_connections", CFG_VAR_INT | CFG_ATOMIC, 0, (1U<<31)-1,
74
+													       fix_max_conns,    0,
75
+		"maximum tls connections number, soft limit"},
73 76
 	{ "no_connect",   CFG_VAR_INT | CFG_ATOMIC,      0,   1,      0,         0,
74 77
 		"if set only accept new connections, never actively open new ones"},
75 78
 	{ "fd_cache",     CFG_VAR_INT | CFG_READONLY,    0,   1,      0,         0,
... ...
@@ -132,6 +135,7 @@ void init_tcp_options()
132 132
 	tcp_default_cfg.con_lifetime=S_TO_TICKS(DEFAULT_TCP_CONNECTION_LIFETIME_S);
133 133
 #ifdef USE_TCP
134 134
 	tcp_default_cfg.max_connections=tcp_max_connections;
135
+	tcp_default_cfg.max_tls_connections=tls_max_connections;
135 136
 #else /*USE_TCP*/
136 137
 	tcp_default_cfg.max_connections=0;
137 138
 #endif /*USE_TCP*/
... ...
@@ -114,7 +114,8 @@ struct cfg_group_tcp{
114 114
 	int connect_timeout_s; /* in s */
115 115
 	int send_timeout; /* in ticks (s fixed to ticks) */
116 116
 	int con_lifetime; /* in ticks (s fixed to ticks) */
117
-	int max_connections;
117
+	int max_connections; /* max tcp connections (includes tls connections) */
118
+	int max_tls_connections; /* max tls connections */
118 119
 	int no_connect; /* do not open any new tcp connection (but accept them) */
119 120
 	int fd_cache; /* on /off */
120 121
 	/* tcp async options */