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 806
 									return TCP_POLL_METHOD; }
806 807
 <INITIAL>{TCP_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
807 808
 									return TCP_MAX_CONNECTIONS; }
809
+<INITIAL>{TLS_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
810
+									return TLS_MAX_CONNECTIONS; }
808 811
 <INITIAL>{TCP_NO_CONNECT}		{ count(); yylval.strval=yytext;
809 812
 									return TCP_NO_CONNECT; }
810 813
 <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 1064
 		#endif
1064 1065
 	}
1065 1066
 	| TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
1067
+	| TLS_MAX_CONNECTIONS EQUAL NUMBER {
1068
+		#ifdef USE_TLS
1069
+			tls_max_connections=$3;
1070
+		#else
1071
+			warn("tls support not compiled in");
1072
+		#endif
1073
+	}
1074
+	| TLS_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
1066 1075
 	| TCP_NO_CONNECT EQUAL NUMBER {
1067 1076
 		#ifdef USE_TCP
1068 1077
 			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 709
 	if (!tcp_disable){
708 710
 		tcp_options_get(&t);
709 711
 		rpc->add(c, "{", &handle);
710
-		rpc->struct_add(handle, "dddddddddddddddddddddd",
712
+		rpc->struct_add(handle, "ddddddddddddddddddddddd",
711 713
 			"connect_timeout", t.connect_timeout_s,
712 714
 			"send_timeout",  TICKS_TO_S(t.send_timeout),
713 715
 			"connection_lifetime",  TICKS_TO_S(t.con_lifetime),
714 716
 			"max_connections(soft)", t.max_connections,
717
+			"max_tls_connections(soft)", t.max_tls_connections,
715 718
 			"no_connect",	t.no_connect,
716 719
 			"fd_cache",		t.fd_cache,
717 720
 			"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 259
 static union sockaddr_union* tcp_source_ipv6=0;
259 260
 #endif
260 261
 
261
-static int* tcp_connections_no=0; /* current open connections */
262
+static int* tcp_connections_no=0; /* current tcp (+tls) open connections */
263
+static int* tls_connections_no=0; /* current tls open connections */
262 264
 
263 265
 /* connection hash table (after ip&port) , includes also aliases */
264 266
 struct tcp_conn_alias** tcpconn_aliases_hash=0;
... ...
@@ -1261,6 +1263,16 @@ struct tcp_connection* tcpconn_connect( union sockaddr_union* server,
1261 1263
 					cfg_get(tcp, tcp_cfg, max_connections));
1262 1264
 		goto error;
1263 1265
 	}
1266
+	if (unlikely(type==PROTO_TLS)) {
1267
+		if (*tls_connections_no >= cfg_get(tcp, tcp_cfg, max_tls_connections)){
1268
+			LM_ERR("ERROR: maximum number of tls connections"
1269
+						" exceeded (%d/%d)\n",
1270
+						*tls_connections_no,
1271
+						cfg_get(tcp, tcp_cfg, max_tls_connections));
1272
+			goto error;
1273
+		}
1274
+	}
1275
+
1264 1276
 	s=tcp_do_connect(server, from, type,  send_flags, &my_name, &si, &state);
1265 1277
 	if (s==-1){
1266 1278
 		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 1861
 							cfg_get(tcp, tcp_cfg, max_connections));
1850 1862
 				return -1;
1851 1863
 			}
1864
+			if (unlikely(dst->proto==PROTO_TLS)) {
1865
+				if (unlikely(*tls_connections_no >=
1866
+							cfg_get(tcp, tcp_cfg, max_tls_connections))){
1867
+					LM_ERR("tcp_send %s: maximum number of"
1868
+							" tls connections exceeded (%d/%d)\n",
1869
+							su2a(&dst->to, sizeof(dst->to)),
1870
+							*tls_connections_no,
1871
+							cfg_get(tcp, tcp_cfg, max_tls_connections));
1872
+					return -1;
1873
+				}
1874
+			}
1852 1875
 			c=tcpconn_new(-1, &dst->to, from, 0, dst->proto,
1853 1876
 							S_CONN_CONNECT);
1854 1877
 			if (unlikely(c==0)){
... ...
@@ -2992,6 +3015,8 @@ inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
2992 3015
 			tcpconn_close_main_fd(tcpconn);
2993 3016
 			tcpconn->flags|=F_CONN_FD_CLOSED;
2994 3017
 			(*tcp_connections_no)--;
3018
+			if (unlikely(tcpconn->type==PROTO_TLS))
3019
+				(*tls_connections_no)--;
2995 3020
 		}
2996 3021
 		_tcpconn_free(tcpconn); /* destroys also the wbuf_q if still present*/
2997 3022
 }
... ...
@@ -3038,6 +3063,8 @@ inline static int tcpconn_put_destroy(struct tcp_connection* tcpconn)
3038 3063
 		tcpconn_close_main_fd(tcpconn);
3039 3064
 		tcpconn->flags|=F_CONN_FD_CLOSED;
3040 3065
 		(*tcp_connections_no)--;
3066
+		if (unlikely(tcpconn->type==PROTO_TLS))
3067
+				(*tls_connections_no)--;
3041 3068
 	}
3042 3069
 	/* all the flags / ops on the tcpconn must be done prior to decrementing
3043 3070
 	 * 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 3683
 				break;
3657 3684
 			}
3658 3685
 			(*tcp_connections_no)++;
3686
+			if (unlikely(tcpconn->type==PROTO_TLS))
3687
+				(*tls_connections_no)++;
3659 3688
 			tcpconn->s=fd;
3660 3689
 			/* add tcpconn to the list*/
3661 3690
 			tcpconn_add(tcpconn);
... ...
@@ -3787,6 +3816,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
3787 3816
 				break;
3788 3817
 			}
3789 3818
 			(*tcp_connections_no)++;
3819
+			if (unlikely(tcpconn->type==PROTO_TLS))
3820
+				(*tls_connections_no)++;
3790 3821
 			tcpconn->s=fd;
3791 3822
 			/* update the timeout*/
3792 3823
 			t=get_ticks_raw();
... ...
@@ -3974,12 +4005,24 @@ static inline int handle_new_connect(struct socket_info* si)
3974 4005
 		TCP_STATS_LOCAL_REJECT();
3975 4006
 		return 1; /* success, because the accept was succesfull */
3976 4007
 	}
4008
+	if (unlikely(si->proto==PROTO_TLS)) {
4009
+		if (unlikely(*tls_connections_no>=cfg_get(tcp, tcp_cfg, max_tls_connections))){
4010
+			LM_ERR("maximum number of tls connections exceeded: %d/%d\n",
4011
+					*tls_connections_no,
4012
+					cfg_get(tcp, tcp_cfg, max_tls_connections));
4013
+			tcp_safe_close(new_sock);
4014
+			TCP_STATS_LOCAL_REJECT();
4015
+			return 1; /* success, because the accept was succesfull */
4016
+		}
4017
+	}
3977 4018
 	if (unlikely(init_sock_opt_accept(new_sock)<0)){
3978 4019
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
3979 4020
 		tcp_safe_close(new_sock);
3980 4021
 		return 1; /* success, because the accept was succesfull */
3981 4022
 	}
3982 4023
 	(*tcp_connections_no)++;
4024
+	if (unlikely(si->proto==PROTO_TLS))
4025
+		(*tls_connections_no)++;
3983 4026
 	/* stats for established connections are incremented after
3984 4027
 	   the first received or sent packet.
3985 4028
 	   Alternatively they could be incremented here for accepted
... ...
@@ -4044,6 +4087,8 @@ static inline int handle_new_connect(struct socket_info* si)
4044 4087
 				"closing socket\n");
4045 4088
 		tcp_safe_close(new_sock);
4046 4089
 		(*tcp_connections_no)--;
4090
+		if (unlikely(si->proto==PROTO_TLS))
4091
+			(*tls_connections_no)--;
4047 4092
 	}
4048 4093
 	return 1; /* accept() was succesfull */
4049 4094
 }
... ...
@@ -4428,6 +4473,8 @@ static inline void tcpconn_destroy_all()
4428 4473
 					tcp_safe_close(fd);
4429 4474
 				}
4430 4475
 				(*tcp_connections_no)--;
4476
+				if (unlikely(c->type==PROTO_TLS))
4477
+					(*tls_connections_no)--;
4431 4478
 			c=next;
4432 4479
 		}
4433 4480
 	}
... ...
@@ -4621,6 +4668,10 @@ void destroy_tcp()
4621 4668
 			shm_free(tcp_connections_no);
4622 4669
 			tcp_connections_no=0;
4623 4670
 		}
4671
+		if (tls_connections_no){
4672
+			shm_free(tls_connections_no);
4673
+			tls_connections_no=0;
4674
+		}
4624 4675
 #ifdef TCP_ASYNC
4625 4676
 		if (tcp_total_wq){
4626 4677
 			shm_free(tcp_total_wq);
... ...
@@ -4677,6 +4728,12 @@ int init_tcp()
4677 4728
 		goto error;
4678 4729
 	}
4679 4730
 	*tcp_connections_no=0;
4731
+	tls_connections_no=shm_malloc(sizeof(int));
4732
+	if (tls_connections_no==0){
4733
+		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
4734
+		goto error;
4735
+	}
4736
+	*tls_connections_no=0;
4680 4737
 	if (INIT_TCP_STATS()!=0) goto error;
4681 4738
 	connection_id=shm_malloc(sizeof(int));
4682 4739
 	if (connection_id==0){
... ...
@@ -4838,7 +4895,9 @@ void tcp_get_info(struct tcp_gen_info *ti)
4838 4895
 {
4839 4896
 	ti->tcp_readers=tcp_children_no;
4840 4897
 	ti->tcp_max_connections=tcp_max_connections;
4898
+	ti->tls_max_connections=tls_max_connections;
4841 4899
 	ti->tcp_connections_no=*tcp_connections_no;
4900
+	ti->tls_connections_no=*tls_connections_no;
4842 4901
 #ifdef TCP_ASYNC
4843 4902
 	ti->tcp_write_queued=*tcp_total_wq;
4844 4903
 #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 135
 	tcp_default_cfg.con_lifetime=S_TO_TICKS(DEFAULT_TCP_CONNECTION_LIFETIME_S);
133 136
 #ifdef USE_TCP
134 137
 	tcp_default_cfg.max_connections=tcp_max_connections;
138
+	tcp_default_cfg.max_tls_connections=tls_max_connections;
135 139
 #else /*USE_TCP*/
136 140
 	tcp_default_cfg.max_connections=0;
137 141
 #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 */