--- embedaddon/lighttpd/src/mod_evasive.c 2014/06/15 20:20:06 1.1.1.2 +++ embedaddon/lighttpd/src/mod_evasive.c 2016/11/02 10:35:00 1.1.1.3 @@ -1,6 +1,9 @@ +#include "first.h" + #include "base.h" #include "log.h" #include "buffer.h" +#include "response.h" #include "plugin.h" @@ -28,6 +31,7 @@ typedef struct { unsigned short max_conns; unsigned short silent; + buffer *location; } plugin_config; typedef struct { @@ -58,6 +62,10 @@ FREE_FUNC(mod_evasive_free) { for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; + if (NULL == s) continue; + + buffer_free(s->location); + free(s); } free(p->config_storage); @@ -75,24 +83,28 @@ SETDEFAULTS_FUNC(mod_evasive_set_defaults) { config_values_t cv[] = { { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "evasive.silent", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "evasive.location", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *)); for (i = 0; i < srv->config_context->used; i++) { + data_config const* config = (data_config const*)srv->config_context->data[i]; plugin_config *s; s = calloc(1, sizeof(plugin_config)); s->max_conns = 0; s->silent = 0; + s->location = buffer_init(); cv[0].destination = &(s->max_conns); cv[1].destination = &(s->silent); + cv[2].destination = s->location; p->config_storage[i] = s; - if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { + if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { return HANDLER_ERROR; } } @@ -108,6 +120,7 @@ static int mod_evasive_patch_connection(server *srv, c PATCH(max_conns); PATCH(silent); + PATCH(location); /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { @@ -125,6 +138,8 @@ static int mod_evasive_patch_connection(server *srv, c PATCH(max_conns); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.silent"))) { PATCH(silent); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.location"))) { + PATCH(location); } } } @@ -138,7 +153,7 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { size_t conns_by_ip = 0; size_t j; - if (con->uri.path->used == 0) return HANDLER_GO_ON; + if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON; mod_evasive_patch_connection(srv, con, p); @@ -185,7 +200,13 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { "turned away. Too many connections."); } - con->http_status = 403; + if (!buffer_is_empty(p->conf.location)) { + response_header_overwrite(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.location)); + con->http_status = 302; + con->file_finished = 1; + } else { + con->http_status = 403; + } con->mode = DIRECT; return HANDLER_FINISHED; }