mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-27 21:44:04 +02:00
[package] uhttpd: protect tcp receive operations with select, make tcp keep-alive optional (#8272)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@24952 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
13ec8222a8
commit
6e21adc1e0
@ -8,7 +8,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=uhttpd
|
PKG_NAME:=uhttpd
|
||||||
PKG_RELEASE:=20
|
PKG_RELEASE:=21
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
PKG_BUILD_DEPENDS := libcyassl liblua
|
PKG_BUILD_DEPENDS := libcyassl liblua
|
||||||
|
@ -51,6 +51,13 @@ config uhttpd main
|
|||||||
# request process.
|
# request process.
|
||||||
option network_timeout 30
|
option network_timeout 30
|
||||||
|
|
||||||
|
# TCP Keep-Alive, send periodic keep-alive probes
|
||||||
|
# over established connections to detect dead peers.
|
||||||
|
# The value is given in seconds to specify the
|
||||||
|
# interval between subsequent probes.
|
||||||
|
# Setting this to 0 will disable TCP keep-alive.
|
||||||
|
option tcp_keepalive 1
|
||||||
|
|
||||||
# Basic auth realm, defaults to local hostname
|
# Basic auth realm, defaults to local hostname
|
||||||
# option realm OpenWrt
|
# option realm OpenWrt
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ start_instance()
|
|||||||
append_arg "$cfg" lua_handler "-L"
|
append_arg "$cfg" lua_handler "-L"
|
||||||
append_arg "$cfg" script_timeout "-t"
|
append_arg "$cfg" script_timeout "-t"
|
||||||
append_arg "$cfg" network_timeout "-T"
|
append_arg "$cfg" network_timeout "-T"
|
||||||
|
append_arg "$cfg" tcp_keepalive "-A"
|
||||||
append_arg "$cfg" error_page "-E"
|
append_arg "$cfg" error_page "-E"
|
||||||
append_arg "$cfg" index_page "-I"
|
append_arg "$cfg" index_page "-I"
|
||||||
|
|
||||||
|
@ -167,6 +167,9 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
|
|||||||
int sz = 0;
|
int sz = 0;
|
||||||
int rsz = 0;
|
int rsz = 0;
|
||||||
|
|
||||||
|
fd_set reader;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
/* first serve data from peek buffer */
|
/* first serve data from peek buffer */
|
||||||
if( cl->peeklen > 0 )
|
if( cl->peeklen > 0 )
|
||||||
{
|
{
|
||||||
@ -180,15 +183,28 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
|
|||||||
/* caller wants more */
|
/* caller wants more */
|
||||||
if( len > 0 )
|
if( len > 0 )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TLS
|
FD_ZERO(&reader);
|
||||||
if( cl->tls )
|
FD_SET(cl->socket, &reader);
|
||||||
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
|
|
||||||
|
|
||||||
if( (sz == 0) || (rsz > 0) )
|
timeout.tv_sec = cl->server->conf->network_timeout;
|
||||||
sz += rsz;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_TLS
|
||||||
|
if( cl->tls )
|
||||||
|
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
|
||||||
|
|
||||||
|
if( (sz == 0) || (rsz > 0) )
|
||||||
|
sz += rsz;
|
||||||
|
}
|
||||||
|
else if( sz == 0 )
|
||||||
|
{
|
||||||
|
sz = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sz;
|
return sz;
|
||||||
@ -233,7 +249,7 @@ int uh_http_sendc(struct client *cl, const char *data, int len)
|
|||||||
|
|
||||||
if( len > 0 )
|
if( len > 0 )
|
||||||
{
|
{
|
||||||
clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
|
clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
|
||||||
ensure_ret(uh_tcp_send(cl, chunk, clen));
|
ensure_ret(uh_tcp_send(cl, chunk, clen));
|
||||||
ensure_ret(uh_tcp_send(cl, data, len));
|
ensure_ret(uh_tcp_send(cl, data, len));
|
||||||
ensure_ret(uh_tcp_send(cl, "\r\n", 2));
|
ensure_ret(uh_tcp_send(cl, "\r\n", 2));
|
||||||
|
@ -127,9 +127,7 @@ static int uh_socket_bind(
|
|||||||
int status;
|
int status;
|
||||||
int bound = 0;
|
int bound = 0;
|
||||||
|
|
||||||
int tcp_ka_idl = 1;
|
int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt;
|
||||||
int tcp_ka_int = 1;
|
|
||||||
int tcp_ka_cnt = 3;
|
|
||||||
|
|
||||||
struct listener *l = NULL;
|
struct listener *l = NULL;
|
||||||
struct addrinfo *addrs = NULL, *p = NULL;
|
struct addrinfo *addrs = NULL, *p = NULL;
|
||||||
@ -157,13 +155,20 @@ static int uh_socket_bind(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TCP keep-alive */
|
/* TCP keep-alive */
|
||||||
if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
|
if( conf->tcp_keepalive > 0 )
|
||||||
setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
|
|
||||||
setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
|
|
||||||
setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) )
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
|
tcp_ka_idl = 1;
|
||||||
strerror(errno));
|
tcp_ka_cnt = 3;
|
||||||
|
tcp_ka_int = conf->tcp_keepalive;
|
||||||
|
|
||||||
|
if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
|
||||||
|
setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
|
||||||
|
setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
|
||||||
|
setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* required to get parallel v4 + v6 working */
|
/* required to get parallel v4 + v6 working */
|
||||||
@ -619,7 +624,7 @@ static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd)
|
|||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
/* master file descriptor list */
|
/* master file descriptor list */
|
||||||
fd_set used_fds, serv_fds, read_fds;
|
fd_set serv_fds;
|
||||||
|
|
||||||
/* working structs */
|
/* working structs */
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
@ -650,10 +655,7 @@ int main (int argc, char **argv)
|
|||||||
void *lib;
|
void *lib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* clear the master and temp sets */
|
|
||||||
FD_ZERO(&used_fds);
|
|
||||||
FD_ZERO(&serv_fds);
|
FD_ZERO(&serv_fds);
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
|
|
||||||
/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
|
/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
@ -722,7 +724,7 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while( (opt = getopt(argc, argv,
|
while( (opt = getopt(argc, argv,
|
||||||
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0
|
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:A:")) > 0
|
||||||
) {
|
) {
|
||||||
switch(opt)
|
switch(opt)
|
||||||
{
|
{
|
||||||
@ -896,6 +898,11 @@ int main (int argc, char **argv)
|
|||||||
conf.network_timeout = atoi(optarg);
|
conf.network_timeout = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* tcp keep-alive */
|
||||||
|
case 'A':
|
||||||
|
conf.tcp_keepalive = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
/* no fork */
|
/* no fork */
|
||||||
case 'f':
|
case 'f':
|
||||||
nofork = 1;
|
nofork = 1;
|
||||||
|
@ -75,6 +75,7 @@ struct config {
|
|||||||
int no_dirlists;
|
int no_dirlists;
|
||||||
int network_timeout;
|
int network_timeout;
|
||||||
int rfc1918_filter;
|
int rfc1918_filter;
|
||||||
|
int tcp_keepalive;
|
||||||
#ifdef HAVE_CGI
|
#ifdef HAVE_CGI
|
||||||
char *cgi_prefix;
|
char *cgi_prefix;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user