1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-21 12:27:27 +03:00

[backfire] merge r22630, r22692, r22805

git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@22962 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
jow
2010-09-06 20:49:31 +00:00
parent 97974216cf
commit 752a6977d2
11 changed files with 500 additions and 360 deletions

View File

@@ -51,8 +51,8 @@ static void uh_config_parse(struct config *conf)
{
FILE *c;
char line[512];
char *user = NULL;
char *pass = NULL;
char *col1 = NULL;
char *col2 = NULL;
char *eol = NULL;
const char *path = conf->file ? conf->file : "/etc/httpd.conf";
@@ -66,35 +66,52 @@ static void uh_config_parse(struct config *conf)
{
if( (line[0] == '/') && (strchr(line, ':') != NULL) )
{
if( !(user = strchr(line, ':')) || (*user++ = 0) ||
!(pass = strchr(user, ':')) || (*pass++ = 0) ||
!(eol = strchr(pass, '\n')) || (*eol++ = 0) )
if( !(col1 = strchr(line, ':')) || (*col1++ = 0) ||
!(col2 = strchr(col1, ':')) || (*col2++ = 0) ||
!(eol = strchr(col2, '\n')) || (*eol++ = 0) )
continue;
if( !uh_auth_add(line, user, pass) )
if( !uh_auth_add(line, col1, col2) )
{
fprintf(stderr,
"Notice: No password set for user %s, ignoring "
"authentication on %s\n", user, line
"authentication on %s\n", col1, line
);
}
}
else if( !strncmp(line, "I:", 2) )
{
if( !(user = strchr(line, ':')) || (*user++ = 0) ||
!(eol = strchr(user, '\n')) || (*eol++ = 0) )
if( !(col1 = strchr(line, ':')) || (*col1++ = 0) ||
!(eol = strchr(col1, '\n')) || (*eol++ = 0) )
continue;
conf->index_file = strdup(user);
conf->index_file = strdup(col1);
}
else if( !strncmp(line, "E404:", 5) )
{
if( !(user = strchr(line, ':')) || (*user++ = 0) ||
!(eol = strchr(user, '\n')) || (*eol++ = 0) )
if( !(col1 = strchr(line, ':')) || (*col1++ = 0) ||
!(eol = strchr(col1, '\n')) || (*eol++ = 0) )
continue;
conf->error_handler = strdup(user);
conf->error_handler = strdup(col1);
}
#ifdef HAVE_CGI
else if( (line[0] == '*') && (strchr(line, ':') != NULL) )
{
if( !(col1 = strchr(line, '*')) || (*col1++ = 0) ||
!(col2 = strchr(col1, ':')) || (*col2++ = 0) ||
!(eol = strchr(col2, '\n')) || (*eol++ = 0) )
continue;
if( !uh_interpreter_add(col1, col2) )
{
fprintf(stderr,
"Unable to add interpreter %s for extension %s: "
"Out of memory\n", col2, col1
);
}
}
#endif
}
fclose(c);
@@ -110,6 +127,10 @@ 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;
struct listener *l = NULL;
struct addrinfo *addrs = NULL, *p = NULL;
@@ -129,12 +150,22 @@ static int uh_socket_bind(
}
/* "address already in use" */
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1 )
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) )
{
perror("setsockopt()");
goto error;
}
/* 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)) )
{
fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
strerror(errno));
}
/* required to get parallel v4 + v6 working */
if( p->ai_family == AF_INET6 )
{
@@ -162,11 +193,7 @@ static int uh_socket_bind(
/* add listener to global list */
if( ! (l = uh_listener_add(sock, conf)) )
{
fprintf(stderr,
"uh_listener_add(): Can not create more than "
"%i listen sockets\n", UH_LIMIT_LISTENERS
);
fprintf(stderr, "uh_listener_add(): Failed to allocate memory\n");
goto error;
}
@@ -343,7 +370,6 @@ static struct http_request * uh_http_header_recv(struct client *cl)
ssize_t blen = sizeof(buffer)-1;
ssize_t rlen = 0;
memset(buffer, 0, sizeof(buffer));
while( blen > 0 )
@@ -359,44 +385,41 @@ static struct http_request * uh_http_header_recv(struct client *cl)
if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
{
/* receive data */
rlen = uh_tcp_peek(cl, bufptr, blen);
ensure_out(rlen = uh_tcp_peek(cl, bufptr, blen));
if( rlen > 0 )
if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) )
{
if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) )
{
blen -= uh_tcp_recv(cl, bufptr, (int)(idxptr - bufptr) + 4);
ensure_out(rlen = uh_tcp_recv(cl, bufptr,
(int)(idxptr - bufptr) + 4));
/* header read complete ... */
return uh_http_header_parse(cl, buffer, sizeof(buffer) - blen - 1);
}
else
{
rlen = uh_tcp_recv(cl, bufptr, rlen);
blen -= rlen;
bufptr += rlen;
}
/* header read complete ... */
blen -= rlen;
return uh_http_header_parse(cl, buffer,
sizeof(buffer) - blen - 1);
}
else
{
/* invalid request (unexpected eof/timeout) */
uh_http_response(cl, 408, "Request Timeout");
return NULL;
ensure_out(rlen = uh_tcp_recv(cl, bufptr, rlen));
blen -= rlen;
bufptr += rlen;
}
}
else
{
/* invalid request (unexpected eof/timeout) */
uh_http_response(cl, 408, "Request Timeout");
return NULL;
}
}
/* request entity too large */
uh_http_response(cl, 413, "Request Entity Too Large");
out:
return NULL;
}
#if defined(HAVE_LUA) || defined(HAVE_CGI)
static int uh_path_match(const char *prefix, const char *url)
{
if( (strstr(url, prefix) == url) &&
@@ -409,23 +432,193 @@ static int uh_path_match(const char *prefix, const char *url)
return 0;
}
#endif
static void uh_dispatch_request(
struct client *cl, struct http_request *req, struct path_info *pin
) {
#ifdef HAVE_CGI
struct interpreter *ipr = NULL;
if( uh_path_match(cl->server->conf->cgi_prefix, pin->name) ||
(ipr = uh_interpreter_lookup(pin->phys)) )
{
uh_cgi_request(cl, req, pin, ipr);
}
else
#endif
{
uh_file_request(cl, req, pin);
}
}
static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd)
{
/* master file descriptor list */
fd_set used_fds, read_fds;
/* working structs */
struct http_request *req;
struct path_info *pin;
struct client *cl;
/* maximum file descriptor number */
int new_fd, cur_fd = 0;
/* clear the master and temp sets */
FD_ZERO(&used_fds);
FD_ZERO(&read_fds);
/* backup server descriptor set */
used_fds = serv_fds;
/* loop */
while(run)
{
/* create a working copy of the used fd set */
read_fds = used_fds;
/* sleep until socket activity */
if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 )
{
perror("select()");
exit(1);
}
/* run through the existing connections looking for data to be read */
for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ )
{
/* is a socket managed by us */
if( FD_ISSET(cur_fd, &read_fds) )
{
/* is one of our listen sockets */
if( FD_ISSET(cur_fd, &serv_fds) )
{
/* handle new connections */
if( (new_fd = accept(cur_fd, NULL, 0)) != -1 )
{
/* add to global client list */
if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL )
{
#ifdef HAVE_TLS
/* setup client tls context */
if( conf->tls )
conf->tls_accept(cl);
#endif
/* add client socket to global fdset */
FD_SET(new_fd, &used_fds);
fd_cloexec(new_fd);
max_fd = max(max_fd, new_fd);
}
/* insufficient resources */
else
{
fprintf(stderr,
"uh_client_add(): Cannot allocate memory\n");
close(new_fd);
}
}
}
/* is a client socket */
else
{
if( ! (cl = uh_client_lookup(cur_fd)) )
{
/* this should not happen! */
fprintf(stderr,
"uh_client_lookup(): No entry for fd %i!\n",
cur_fd);
goto cleanup;
}
/* parse message header */
if( (req = uh_http_header_recv(cl)) != NULL )
{
/* RFC1918 filtering required? */
if( conf->rfc1918_filter &&
sa_rfc1918(&cl->peeraddr) &&
!sa_rfc1918(&cl->servaddr) )
{
uh_http_sendhf(cl, 403, "Forbidden",
"Rejected request from RFC1918 IP "
"to public server address");
}
else
#ifdef HAVE_LUA
/* Lua request? */
if( conf->lua_state &&
uh_path_match(conf->lua_prefix, req->url) )
{
conf->lua_request(cl, req, conf->lua_state);
}
else
#endif
/* dispatch request */
if( (pin = uh_path_lookup(cl, req->url)) != NULL )
{
/* auth ok? */
if( uh_auth_check(cl, req, pin) )
uh_dispatch_request(cl, req, pin);
}
/* 404 */
else
{
/* Try to invoke an error handler */
pin = uh_path_lookup(cl, conf->error_handler);
if( pin && uh_auth_check(cl, req, pin) )
{
req->redirect_status = 404;
uh_dispatch_request(cl, req, pin);
}
else
{
uh_http_sendhf(cl, 404, "Not Found",
"No such file or directory");
}
}
}
#ifdef HAVE_TLS
/* free client tls context */
if( conf->tls )
conf->tls_close(cl);
#endif
cleanup:
/* close client socket */
close(cur_fd);
FD_CLR(cur_fd, &used_fds);
/* remove from global client list */
uh_client_remove(cur_fd);
}
}
}
}
#ifdef HAVE_LUA
/* destroy the Lua state */
if( conf->lua_state != NULL )
conf->lua_close(conf->lua_state);
#endif
}
int main (int argc, char **argv)
{
#ifdef HAVE_LUA
/* Lua runtime */
lua_State *L = NULL;
#endif
/* master file descriptor list */
fd_set used_fds, serv_fds, read_fds;
/* working structs */
struct addrinfo hints;
struct http_request *req;
struct path_info *pin;
struct client *cl;
struct sigaction sa;
struct config conf;
@@ -433,7 +626,7 @@ int main (int argc, char **argv)
sigset_t ss;
/* maximum file descriptor number */
int new_fd, cur_fd, max_fd = 0;
int cur_fd, max_fd = 0;
#ifdef HAVE_TLS
int tls = 0;
@@ -525,7 +718,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:t:T:")) > 0
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0
) {
switch(opt)
{
@@ -658,6 +851,21 @@ int main (int argc, char **argv)
case 'x':
conf.cgi_prefix = optarg;
break;
/* interpreter */
case 'i':
if( (optarg[0] == '.') && (port = strchr(optarg, '=')) )
{
*port++ = 0;
uh_interpreter_add(optarg, port);
}
else
{
fprintf(stderr, "Error: Invalid interpreter: %s\n",
optarg);
exit(1);
}
break;
#endif
#ifdef HAVE_LUA
@@ -740,6 +948,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_CGI
" -x string URL prefix for CGI handler, default is '/cgi-bin'\n"
" -i .ext=path Use interpreter at path for files with the given extension\n"
#endif
#if defined(HAVE_CGI) || defined(HAVE_LUA)
" -t seconds CGI and Lua script timeout in seconds, default is 60\n"
@@ -830,7 +1039,7 @@ int main (int argc, char **argv)
if( ! conf.lua_prefix )
conf.lua_prefix = "/lua";
L = conf.lua_init(conf.lua_handler);
conf.lua_state = conf.lua_init(conf.lua_handler);
}
}
#endif
@@ -865,166 +1074,13 @@ int main (int argc, char **argv)
}
}
/* backup server descriptor set */
used_fds = serv_fds;
/* loop */
while(run)
{
/* create a working copy of the used fd set */
read_fds = used_fds;
/* sleep until socket activity */
if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 )
{
perror("select()");
exit(1);
}
/* run through the existing connections looking for data to be read */
for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ )
{
/* is a socket managed by us */
if( FD_ISSET(cur_fd, &read_fds) )
{
/* is one of our listen sockets */
if( FD_ISSET(cur_fd, &serv_fds) )
{
/* handle new connections */
if( (new_fd = accept(cur_fd, NULL, 0)) != -1 )
{
/* add to global client list */
if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL )
{
#ifdef HAVE_TLS
/* setup client tls context */
if( conf.tls )
conf.tls_accept(cl);
#endif
/* add client socket to global fdset */
FD_SET(new_fd, &used_fds);
fd_cloexec(new_fd);
max_fd = max(max_fd, new_fd);
}
/* insufficient resources */
else
{
fprintf(stderr,
"uh_client_add(): Can not manage more than "
"%i client sockets, connection dropped\n",
UH_LIMIT_CLIENTS
);
close(new_fd);
}
}
}
/* is a client socket */
else
{
if( ! (cl = uh_client_lookup(cur_fd)) )
{
/* this should not happen! */
fprintf(stderr,
"uh_client_lookup(): No entry for fd %i!\n",
cur_fd);
goto cleanup;
}
/* parse message header */
if( (req = uh_http_header_recv(cl)) != NULL )
{
/* RFC1918 filtering required? */
if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) &&
!sa_rfc1918(&cl->servaddr) )
{
uh_http_sendhf(cl, 403, "Forbidden",
"Rejected request from RFC1918 IP to public server address");
}
else
#ifdef HAVE_LUA
/* Lua request? */
if( L && uh_path_match(conf.lua_prefix, req->url) )
{
conf.lua_request(cl, req, L);
}
else
#endif
/* dispatch request */
if( (pin = uh_path_lookup(cl, req->url)) != NULL )
{
/* auth ok? */
if( uh_auth_check(cl, req, pin) )
{
#ifdef HAVE_CGI
if( uh_path_match(conf.cgi_prefix, pin->name) )
{
uh_cgi_request(cl, req, pin);
}
else
#endif
{
uh_file_request(cl, req, pin);
}
}
}
/* 404 */
else
{
/* Try to invoke an error handler */
pin = uh_path_lookup(cl, conf.error_handler);
if( pin && uh_auth_check(cl, req, pin) )
{
req->redirect_status = 404;
#ifdef HAVE_CGI
if( uh_path_match(conf.cgi_prefix, pin->name) )
{
uh_cgi_request(cl, req, pin);
}
else
#endif
{
uh_file_request(cl, req, pin);
}
}
else
{
uh_http_sendhf(cl, 404, "Not Found",
"No such file or directory");
}
}
}
#ifdef HAVE_TLS
/* free client tls context */
if( conf.tls )
conf.tls_close(cl);
#endif
cleanup:
/* close client socket */
close(cur_fd);
FD_CLR(cur_fd, &used_fds);
/* remove from global client list */
uh_client_remove(cur_fd);
}
}
}
}
/* server main loop */
uh_mainloop(&conf, serv_fds, max_fd);
#ifdef HAVE_LUA
/* destroy the Lua state */
if( L != NULL )
conf.lua_close(L);
if( conf.lua_state != NULL )
conf.lua_close(conf.lua_state);
#endif
return 0;