aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2011-01-09 23:35:45 +0000
committerJo-Philipp Wich <jow@openwrt.org>2011-01-09 23:35:45 +0000
commitf38a320e693d951e6bcd0fb2ee4e81855d48a21c (patch)
tree35c5a85b50eb565c3b57409ea589d17e053ec2a1
parent8067116c10bdf7c34f292ae64c4b6ed6193d3182 (diff)
downloadupstream-f38a320e693d951e6bcd0fb2ee4e81855d48a21c.tar.gz
upstream-f38a320e693d951e6bcd0fb2ee4e81855d48a21c.tar.bz2
upstream-f38a320e693d951e6bcd0fb2ee4e81855d48a21c.zip
uhttpd: protect tcp receive operations with select, make tcp keep-alive optional (#8272)
SVN-Revision: 24952
-rw-r--r--package/uhttpd/Makefile2
-rw-r--r--package/uhttpd/files/uhttpd.config7
-rwxr-xr-xpackage/uhttpd/files/uhttpd.init1
-rw-r--r--package/uhttpd/src/uhttpd-utils.c30
-rw-r--r--package/uhttpd/src/uhttpd.c35
-rw-r--r--package/uhttpd/src/uhttpd.h1
6 files changed, 54 insertions, 22 deletions
diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile
index a0b7d24ebf..bba7ac53ad 100644
--- a/package/uhttpd/Makefile
+++ b/package/uhttpd/Makefile
@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=uhttpd
-PKG_RELEASE:=20
+PKG_RELEASE:=21
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_BUILD_DEPENDS := libcyassl liblua
diff --git a/package/uhttpd/files/uhttpd.config b/package/uhttpd/files/uhttpd.config
index a29910a65f..08ca5e5e02 100644
--- a/package/uhttpd/files/uhttpd.config
+++ b/package/uhttpd/files/uhttpd.config
@@ -51,6 +51,13 @@ config uhttpd main
# request process.
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
# option realm OpenWrt
diff --git a/package/uhttpd/files/uhttpd.init b/package/uhttpd/files/uhttpd.init
index f8f1754e90..069e16fff1 100755
--- a/package/uhttpd/files/uhttpd.init
+++ b/package/uhttpd/files/uhttpd.init
@@ -66,6 +66,7 @@ start_instance()
append_arg "$cfg" lua_handler "-L"
append_arg "$cfg" script_timeout "-t"
append_arg "$cfg" network_timeout "-T"
+ append_arg "$cfg" tcp_keepalive "-A"
append_arg "$cfg" error_page "-E"
append_arg "$cfg" index_page "-I"
diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c
index c7bc867aab..ac00af824e 100644
--- a/package/uhttpd/src/uhttpd-utils.c
+++ b/package/uhttpd/src/uhttpd-utils.c
@@ -167,6 +167,9 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
int sz = 0;
int rsz = 0;
+ fd_set reader;
+ struct timeval timeout;
+
/* first serve data from peek buffer */
if( cl->peeklen > 0 )
{
@@ -180,15 +183,28 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
/* caller wants more */
if( len > 0 )
{
+ FD_ZERO(&reader);
+ FD_SET(cl->socket, &reader);
+
+ timeout.tv_sec = cl->server->conf->network_timeout;
+ 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
+ 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);
+ rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
- if( (sz == 0) || (rsz > 0) )
- sz += rsz;
+ if( (sz == 0) || (rsz > 0) )
+ sz += rsz;
+ }
+ else if( sz == 0 )
+ {
+ sz = -1;
+ }
}
return sz;
@@ -233,7 +249,7 @@ int uh_http_sendc(struct client *cl, const char *data, int len)
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, data, len));
ensure_ret(uh_tcp_send(cl, "\r\n", 2));
diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c
index 2c7755f8da..1fd21344fe 100644
--- a/package/uhttpd/src/uhttpd.c
+++ b/package/uhttpd/src/uhttpd.c
@@ -127,9 +127,7 @@ static int uh_socket_bind(
int status;
int bound = 0;
- int tcp_ka_idl = 1;
- int tcp_ka_int = 1;
- int tcp_ka_cnt = 3;
+ int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt;
struct listener *l = NULL;
struct addrinfo *addrs = NULL, *p = NULL;
@@ -157,13 +155,20 @@ static int uh_socket_bind(
}
/* TCP keep-alive */
- 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)) )
+ if( conf->tcp_keepalive > 0 )
{
- fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
- strerror(errno));
+ tcp_ka_idl = 1;
+ 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 */
@@ -619,7 +624,7 @@ static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd)
int main (int argc, char **argv)
{
/* master file descriptor list */
- fd_set used_fds, serv_fds, read_fds;
+ fd_set serv_fds;
/* working structs */
struct addrinfo hints;
@@ -650,10 +655,7 @@ int main (int argc, char **argv)
void *lib;
#endif
- /* clear the master and temp sets */
- FD_ZERO(&used_fds);
FD_ZERO(&serv_fds);
- FD_ZERO(&read_fds);
/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
sa.sa_flags = 0;
@@ -722,7 +724,7 @@ int main (int argc, char **argv)
#endif
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)
{
@@ -896,6 +898,11 @@ int main (int argc, char **argv)
conf.network_timeout = atoi(optarg);
break;
+ /* tcp keep-alive */
+ case 'A':
+ conf.tcp_keepalive = atoi(optarg);
+ break;
+
/* no fork */
case 'f':
nofork = 1;
diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h
index 6747b905ff..ff058d62bf 100644
--- a/package/uhttpd/src/uhttpd.h
+++ b/package/uhttpd/src/uhttpd.h
@@ -75,6 +75,7 @@ struct config {
int no_dirlists;
int network_timeout;
int rfc1918_filter;
+ int tcp_keepalive;
#ifdef HAVE_CGI
char *cgi_prefix;
#endif