184 lines
5 KiB
Diff
184 lines
5 KiB
Diff
--- mod_limitipconn.c Fri Apr 12 13:54:49 2002
|
|
+++ ../../files/mod_limitipconn.c Thu Jun 5 17:39:10 2003
|
|
@@ -34,7 +34,7 @@
|
|
#include "scoreboard.h"
|
|
|
|
#define MODULE_NAME "mod_limitipconn"
|
|
-#define MODULE_VERSION "0.04"
|
|
+#define MODULE_VERSION "0.05"
|
|
|
|
module MODULE_VAR_EXPORT limitipconn_module;
|
|
|
|
@@ -59,62 +59,34 @@
|
|
return (void *) cfg;
|
|
}
|
|
|
|
-static int limitipconn_handler(request_rec *r)
|
|
+static int is_limitable(limitipconn_dir_config *cfg, request_rec *r, char *uri)
|
|
{
|
|
- /* get configuration information */
|
|
- limitipconn_dir_config *cfg = (limitipconn_dir_config *)
|
|
- ap_get_module_config(r->per_dir_config, &limitipconn_module);
|
|
+ /* Content-type of the current request */
|
|
+ const char *content_type;
|
|
|
|
/* convert Apache arrays to normal C arrays */
|
|
char **nolim = (char **) cfg->no_limit->elts;
|
|
char **exlim = (char **) cfg->excl_limit->elts;
|
|
|
|
- const char *address;
|
|
-
|
|
/* loop index variable */
|
|
int i;
|
|
|
|
- /* running count of number of connections from this address */
|
|
- int ip_count = 0;
|
|
-
|
|
- /* Content-type of the current request */
|
|
- const char *content_type;
|
|
-
|
|
- /* scoreboard data structure */
|
|
- short_score score_record;
|
|
-
|
|
- /* We decline to handle subrequests: otherwise, in the next step we
|
|
- * could get into an infinite loop. */
|
|
- if (!ap_is_initial_req(r)) {
|
|
- return DECLINED;
|
|
- }
|
|
-
|
|
/* Look up the Content-type of this request. We need a subrequest
|
|
* here since this module might be called before the URI has been
|
|
* translated into a MIME type. */
|
|
- content_type = ap_sub_req_lookup_uri(r->uri, r)->content_type;
|
|
+ content_type = ap_sub_req_lookup_uri(uri, r)->content_type;
|
|
|
|
/* If there's no Content-type, use the default. */
|
|
if (!content_type) {
|
|
content_type = ap_default_type(r);
|
|
}
|
|
|
|
-#ifdef RECORD_FORWARD
|
|
- if ((address = ap_table_get(r->headers_in, "X-Forwarded-For")) == NULL)
|
|
-#endif
|
|
- address = r->connection->remote_ip;
|
|
-
|
|
- /* A limit value of 0 by convention means no limit. */
|
|
- if (cfg->limit == 0) {
|
|
- return OK;
|
|
- }
|
|
-
|
|
/* Cycle through the exempt list; if our content_type is exempt,
|
|
- * return OK */
|
|
+ * return 0 */
|
|
for (i = 0; i < cfg->no_limit->nelts; i++) {
|
|
if ((ap_strcasecmp_match(content_type, nolim[i]) == 0)
|
|
|| (strncmp(nolim[i], content_type, strlen(nolim[i])) == 0)) {
|
|
- return OK;
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
@@ -129,9 +101,49 @@
|
|
}
|
|
}
|
|
if (excused) {
|
|
- return OK;
|
|
+ return 0;
|
|
}
|
|
}
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int limitipconn_handler(request_rec *r)
|
|
+{
|
|
+ /* get configuration information */
|
|
+ limitipconn_dir_config *cfg = (limitipconn_dir_config *)
|
|
+ ap_get_module_config(r->per_dir_config, &limitipconn_module);
|
|
+
|
|
+ const char *address;
|
|
+
|
|
+ /* loop index variable */
|
|
+ int i;
|
|
+
|
|
+ /* running count of number of connections from this address */
|
|
+ int ip_count = 0;
|
|
+
|
|
+ /* scoreboard data structure */
|
|
+ short_score score_record;
|
|
+
|
|
+ /* We decline to handle subrequests: otherwise, in the next step we
|
|
+ * could get into an infinite loop. */
|
|
+ if (!ap_is_initial_req(r)) {
|
|
+ return DECLINED;
|
|
+ }
|
|
+
|
|
+#ifdef RECORD_FORWARD
|
|
+ if ((address = ap_table_get(r->headers_in, "X-Forwarded-For")) == NULL)
|
|
+#endif
|
|
+ address = r->connection->remote_ip;
|
|
+
|
|
+ /* A limit value of 0 by convention means no limit. */
|
|
+ if (cfg->limit == 0) {
|
|
+ return OK;
|
|
+ }
|
|
+
|
|
+ /* If the content-type isn't limitable, return OK */
|
|
+ if (!is_limitable(cfg, r, r->uri)) {
|
|
+ return OK;
|
|
+ }
|
|
|
|
/* Count up the number of connections we are handling right now from
|
|
* this IP address */
|
|
@@ -153,7 +165,51 @@
|
|
|| (strcmp(address, score_record.fwdclient) == 0)
|
|
#endif
|
|
) {
|
|
- ip_count++;
|
|
+ /* Try to determine the URI from what's stored of the request in the
|
|
+ scoreboard. Hopefully we'll get enough of it to be able to determine
|
|
+ the content-type. */
|
|
+
|
|
+ /* A copy of the HTTP request from the scoreboard */
|
|
+ char request[64];
|
|
+
|
|
+ /* The request's URI */
|
|
+ char *uri;
|
|
+
|
|
+ /* A temporary pointer used to find the end of the URI */
|
|
+ char *c;
|
|
+
|
|
+ /* One if we were unable to find a full URI in the request, zero otherwise */
|
|
+ int full_request = 0;
|
|
+
|
|
+ /* Get a copy of the request line from the scoreboard */
|
|
+ strncpy(request, score_record.request, 64);
|
|
+ request[63] = 0;
|
|
+
|
|
+ /* Separate out the method */
|
|
+ for (uri = request; *uri; uri++) {
|
|
+ if (*uri == ' ') {
|
|
+ uri++;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Find the space which separates the URI from the HTTP version */
|
|
+ for (c = uri; *c; c++) {
|
|
+ if (*c == ' ') {
|
|
+ *c = 0;
|
|
+ full_request = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* If we don't see the full request string, then be stringy
|
|
+ and assume that the request is limitable. This was the
|
|
+ behavior before the module was modified to try to be
|
|
+ smarter. */
|
|
+
|
|
+ if (*uri && !full_request || is_limitable(cfg, r, uri)) {
|
|
+ ip_count++;
|
|
+ }
|
|
}
|
|
break;
|
|
case
|