Browse code

core: add an option to trigger also an RST on tcp connection close

- This gives an option to also send RST in case kamailio closes the
connection. There are cases where a FIN,ACK back forth leaves
the connection in the host in TIME_WAIT state, but the ports on both
sides are fixed. This leads to no request can send until
the TIME_WAIT state is gone.

Rick Barenthin authored on 03/05/2022 17:42:31 • Daniel-Constantin Mierla committed on 16/05/2022 06:01:02
Showing 5 changed files
... ...
@@ -421,6 +421,7 @@ TCP_OPT_CRLF_PING	"tcp_crlf_ping"
421 421
 TCP_OPT_ACCEPT_NO_CL	"tcp_accept_no_cl"
422 422
 TCP_OPT_ACCEPT_HEP3	"tcp_accept_hep3"
423 423
 TCP_OPT_ACCEPT_HAPROXY	"tcp_accept_haproxy"
424
+TCP_OPT_CLOSE_RST	"tcp_close_rst"
424 425
 TCP_CLONE_RCVBUF	"tcp_clone_rcvbuf"
425 426
 TCP_REUSE_PORT		"tcp_reuse_port"
426 427
 TCP_WAIT_DATA	"tcp_wait_data"
... ...
@@ -917,6 +918,7 @@ IMPORTFILE      "import_file"
917 918
 									return TCP_OPT_ACCEPT_HEP3; }
918 919
 <INITIAL>{TCP_OPT_ACCEPT_HAPROXY}	{ count(); yylval.strval=yytext;
919 920
 									return TCP_OPT_ACCEPT_HAPROXY; }
921
+<INITIAL>{TCP_OPT_CLOSE_RST}	{ count(); yylval.strval=yytext; return TCP_OPT_CLOSE_RST; }
920 922
 <INITIAL>{TCP_CLONE_RCVBUF}		{ count(); yylval.strval=yytext;
921 923
 									return TCP_CLONE_RCVBUF; }
922 924
 <INITIAL>{TCP_REUSE_PORT}	{ count(); yylval.strval=yytext; return TCP_REUSE_PORT; }
... ...
@@ -450,6 +450,7 @@ extern char *default_routename;
450 450
 %token TCP_OPT_ACCEPT_NO_CL
451 451
 %token TCP_OPT_ACCEPT_HEP3
452 452
 %token TCP_OPT_ACCEPT_HAPROXY
453
+%token TCP_OPT_CLOSE_RST
453 454
 %token TCP_CLONE_RCVBUF
454 455
 %token TCP_REUSE_PORT
455 456
 %token TCP_WAIT_DATA
... ...
@@ -1301,6 +1302,14 @@ assign_stm:
1301 1302
 		#endif
1302 1303
 	}
1303 1304
 	| TCP_OPT_ACCEPT_HAPROXY EQUAL error { yyerror("boolean value expected"); }
1305
+	| TCP_OPT_CLOSE_RST EQUAL NUMBER {
1306
+         #ifdef USE_TCP
1307
+             tcp_default_cfg.close_rst=$3;
1308
+         #else
1309
+             warn("tcp support not compiled in");
1310
+         #endif
1311
+     }
1312
+     | TCP_OPT_CLOSE_RST EQUAL error { yyerror("boolean value expected"); }
1304 1313
 
1305 1314
 	| TCP_CLONE_RCVBUF EQUAL NUMBER {
1306 1315
 		#ifdef USE_TCP
... ...
@@ -3209,6 +3209,13 @@ inline static void tcpconn_close_main_fd(struct tcp_connection* tcpconn)
3209 3209
 #ifdef TCP_FD_CACHE
3210 3210
 	if (likely(cfg_get(tcp, tcp_cfg, fd_cache))) shutdown(fd, SHUT_RDWR);
3211 3211
 #endif /* TCP_FD_CACHE */
3212
+	if(unlikely(cfg_get(tcp, tcp_cfg, close_rst))) {
3213
+		struct linger sl = {
3214
+				.l_onoff = 1,  /* non-zero value enables linger option in kernel */
3215
+				.l_linger = 0, /* timeout interval in seconds */
3216
+		};
3217
+		setsockopt(fd, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
3218
+	}
3212 3219
 	if (unlikely(tcp_safe_close(fd)<0))
3213 3220
 		LM_ERR("(%p): %s close(%d) failed (flags 0x%x): %s (%d)\n", tcpconn,
3214 3221
 					su2a(&tcpconn->rcv.src_su, sizeof(tcpconn->rcv.src_su)),
... ...
@@ -110,6 +110,8 @@ static cfg_def_t tcp_cfg_def[] = {
110 110
 		"reuse TCP ports "},
111 111
 	{ "wait_data_ms",  CFG_VAR_INT | CFG_ATOMIC,      0, 7200000, 0,        0,
112 112
 		"wait for data on new tcp connetions (milliseconds)"},
113
+	{ "close_rst",     CFG_VAR_INT | CFG_READONLY,    0,   1,      0,         0,
114
+			"trigger an RST on connection close"},
113 115
 	/* internal and/or "fixed" versions of some vars
114 116
 	   (not supposed to be writeable, read will provide only debugging value*/
115 117
 	{ "rd_buf_size", CFG_VAR_INT | CFG_ATOMIC,    512,    16777216,  0,         0,
... ...
@@ -167,6 +169,7 @@ void init_tcp_options()
167 169
 	tcp_default_cfg.wq_blk_size=DEFAULT_TCP_WBUF_SIZE;
168 170
 	tcp_default_cfg.reuse_port=0;
169 171
 	tcp_default_cfg.wait_data_ms=5000;
172
+	tcp_default_cfg.close_rst=0;
170 173
 }
171 174
 
172 175
 
... ...
@@ -139,6 +139,7 @@ struct cfg_group_tcp{
139 139
 	int accept_no_cl;  /* on/off - accept messages without content-length */
140 140
 	int reuse_port;  /* enable SO_REUSEPORT */
141 141
 	int wait_data_ms;  /* wait for data in milliseconds */
142
+	int close_rst; /* on /off trigger an RST on connection close */
142 143
 
143 144
 	/* internal, "fixed" vars */
144 145
 	unsigned int rd_buf_size; /* read buffer size (should be > max. datagram)*/