From 59f3aa3a9baeab8c8277332e75a83f134d1e026a Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Thu, 24 Jun 2004 16:07:04 +0000 Subject: [PATCH] nginx-0.0.7-2004-06-24-20:07:04 import --- auto/modules | 6 + auto/options | 2 + auto/sources | 4 + src/core/ngx_inet.c | 15 +- src/http/modules/ngx_http_access_handler.c | 207 +++++++++++++++++++++ src/http/modules/ngx_http_status_handler.c | 60 +++++- src/http/ngx_http.c | 8 + src/http/ngx_http_core_module.h | 4 + src/http/ngx_http_request.c | 12 +- src/os/win32/ngx_process_cycle.c | 2 + 10 files changed, 306 insertions(+), 14 deletions(-) create mode 100644 src/http/modules/ngx_http_access_handler.c diff --git a/auto/modules b/auto/modules index cd07cfc4e..55e10a7c4 100644 --- a/auto/modules +++ b/auto/modules @@ -66,6 +66,12 @@ fi HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE $HTTP_INDEX_MODULE" +if [ $HTTP_ACCESS = YES ]; then + have=NGX_HTTP_ACCESS . auto/have + HTTP_MODULES="$HTTP_MODULES $HTTP_ACCESS_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS" +fi + if [ $HTTP_STATUS = YES ]; then have=NGX_HTTP_STATUS . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE" diff --git a/auto/options b/auto/options index 7a6e36dfd..a2e01a2b7 100644 --- a/auto/options +++ b/auto/options @@ -32,6 +32,7 @@ USE_THREADS=NO HTTP_CHARSET=YES HTTP_GZIP=YES HTTP_SSI=YES +HTTP_ACCESS=YES HTTP_STATUS=YES HTTP_REWRITE=YES HTTP_PROXY=YES @@ -85,6 +86,7 @@ do --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_ssi_module) HTTP_SSI=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; + --without-http_access_module) HTTP_ACCESS=NO ;; --without-http_status_module) HTTP_STATUS=NO ;; --without-http_rewrite_module) HTTP_REWRITE=NO ;; --without-http_proxy_module) HTTP_PROXY=NO ;; diff --git a/auto/sources b/auto/sources index 6801f27f2..4827f154b 100644 --- a/auto/sources +++ b/auto/sources @@ -248,6 +248,10 @@ HTTP_SSI_FILTER_MODULE=ngx_http_ssi_filter_module HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter.c +HTTP_ACCESS_MODULE=ngx_http_access_module +HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c + + HTTP_STATUS_MODULE=ngx_http_status_module HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_handler.c diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 5c032a2d0..68be0ef02 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -170,6 +170,7 @@ size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len) ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr) { + ngx_int_t m; ngx_uint_t i; ngx_inet_cidr_t *in_cidr; @@ -192,10 +193,20 @@ ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr) return NGX_ERROR; } - in_cidr->mask = ngx_atoi(&text->data[i + 1], text->len - (i + 1)); - if (in_cidr->mask == (in_addr_t) NGX_ERROR) { + m = ngx_atoi(&text->data[i + 1], text->len - (i + 1)); + if (m == NGX_ERROR) { return NGX_ERROR; } + if (m == 0) { + + /* the x86 compilers use the shl instruction that shifts by modulo 32 */ + + in_cidr->mask = 0; + return NGX_OK; + } + + in_cidr->mask = (ngx_uint_t) (0 - (1 << (32 - m))); + return NGX_OK; } diff --git a/src/http/modules/ngx_http_access_handler.c b/src/http/modules/ngx_http_access_handler.c new file mode 100644 index 000000000..95e4f773b --- /dev/null +++ b/src/http/modules/ngx_http_access_handler.c @@ -0,0 +1,207 @@ + +#include +#include +#include + + +/* AF_INET only */ + +typedef struct { + in_addr_t mask; + in_addr_t addr; + unsigned deny; +} ngx_http_access_rule_t; + + +typedef struct { + ngx_array_t *rules; /* array of ngx_http_access_rule_t */ +} ngx_http_access_loc_conf_t; + + +static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r); +static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle); + + +static ngx_command_t ngx_http_access_commands[] = { + + { ngx_string("allow"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_access_rule, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("deny"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_access_rule, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + + +ngx_http_module_t ngx_http_access_module_ctx = { + NULL, /* pre conf */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_access_create_loc_conf, /* create location configuration */ + ngx_http_access_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_access_module = { + NGX_MODULE, + &ngx_http_access_module_ctx, /* module context */ + ngx_http_access_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + ngx_http_access_init, /* init module */ + NULL /* init child */ +}; + + +static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r) +{ + ngx_uint_t i; + struct sockaddr_in *addr_in; + ngx_http_access_rule_t *rule; + ngx_http_access_loc_conf_t *alcf; + + alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module); + + if (alcf->rules == NULL) { + return NGX_OK; + } + + /* AF_INET only */ + + addr_in = (struct sockaddr_in *) r->connection->sockaddr; + + rule = alcf->rules->elts; + for (i = 0; i < alcf->rules->nelts; i++) { + + if ((addr_in->sin_addr.s_addr & rule[i].mask) == rule[i].addr) { + if (rule[i].deny) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "access forbidden by rule"); + + return NGX_HTTP_FORBIDDEN; + } + + return NGX_OK; + } + } + + return NGX_OK; +} + + +static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_access_loc_conf_t *alcf = conf; + + ngx_str_t *value; + ngx_inet_cidr_t in_cidr; + ngx_http_access_rule_t *rule; + + if (alcf->rules == NULL) { + alcf->rules = ngx_create_array(cf->pool, 5, + sizeof(ngx_http_access_rule_t)); + if (alcf->rules == NULL) { + return NGX_CONF_ERROR; + } + } + + if (!(rule = ngx_push_array(alcf->rules))) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + rule->deny = (value[0].data[0] == 'd') ? 1 : 0; + + if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) { + rule->mask = 0; + rule->addr = 0; + + return NGX_CONF_OK; + } + + rule->addr = inet_addr((char *) value[1].data); + + if (rule->addr != INADDR_NONE) { + rule->mask = 0xffffffff; + + return NGX_CONF_OK; + } + + if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid paramter \"%s\"", + value[1].data); + return NGX_CONF_ERROR; + } + + rule->mask = in_cidr.mask; + rule->addr = in_cidr.addr; + + return NGX_CONF_OK; +} + + +static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_access_loc_conf_t *conf; + + if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_access_loc_conf_t)))) { + return NGX_CONF_ERROR; + } + + return conf; +} + + +static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child) +{ + ngx_http_access_loc_conf_t *prev = parent; + ngx_http_access_loc_conf_t *conf = child; + + if (conf->rules == NULL) { + conf->rules = prev->rules; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle) +{ + ngx_http_handler_pt *h; + ngx_http_conf_ctx_t *ctx; + ngx_http_core_main_conf_t *cmcf; + + ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; + cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; + + h = ngx_push_array(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_access_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_status_handler.c b/src/http/modules/ngx_http_status_handler.c index 2f361b0c7..b7270363f 100644 --- a/src/http/modules/ngx_http_status_handler.c +++ b/src/http/modules/ngx_http_status_handler.c @@ -46,6 +46,7 @@ ngx_module_t ngx_http_status_module = { static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r) { + u_char ch; size_t len; ngx_int_t rc; ngx_uint_t i, dash; @@ -93,11 +94,20 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r) rq = c[i].data; if (rq && rq->signature == NGX_HTTP_MODULE) { + /* STUB: should be NGX_PID_T_LEN */ + len += NGX_INT64_LEN /* pid */ + + 1 + NGX_INT32_LEN /* connection */ + + 1 + 1 /* state */ + + 1 + c[i].addr_text.len + + 1 + rq->server_name->len + + 2; /* "\r\n" */ + if (rq->request_line.len) { - len += NGX_INT32_LEN + 1 + rq->request_line.len + 2 + 2; - dash = 0; + len += 1 + rq->request_line.len + 2; } + dash = 0; + continue; } @@ -117,28 +127,60 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r) rq = c[i].data; if (rq && rq->signature == NGX_HTTP_MODULE) { -#if 0 + b->last += ngx_snprintf((char *) b->last, + /* STUB: should be NGX_PID_T_LEN */ + NGX_INT64_LEN + NGX_INT32_LEN, + PID_T_FMT " %u", ngx_pid, i); + switch (rq->http_state) { case NGX_HTTP_INITING_REQUEST_STATE: + ch = 'I'; + break; + + case NGX_HTTP_READING_REQUEST_STATE: + ch = 'R'; + break; + + case NGX_HTTP_PROCESS_REQUEST_STATE: + ch = 'P'; + break; + + case NGX_HTTP_WRITING_REQUEST_STATE: + ch = 'W'; + break; case NGX_HTTP_KEEPALIVE_STATE: + ch = 'K'; + break; + + default: + ch = '?'; } -#endif + + *(b->last++) = ' '; + *(b->last++) = ch; + + *(b->last++) = ' '; + b->last = ngx_cpymem(b->last, c[i].addr_text.data, + c[i].addr_text.len); + + *(b->last++) = ' '; + b->last = ngx_cpymem(b->last, rq->server_name->data, + rq->server_name->len); if (rq->request_line.len) { - b->last += ngx_snprintf((char *) b->last, NGX_INT32_LEN, - "%u", i); *(b->last++) = ' '; - *(b->last++) = '"'; b->last = ngx_cpymem(b->last, r->request_line.data, r->request_line.len); *(b->last++) = '"'; - *(b->last++) = CR; *(b->last++) = LF; - dash = 0; } + *(b->last++) = CR; *(b->last++) = LF; + + dash = 0; + continue; } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 9e040d6f6..6fca25400 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -230,6 +230,8 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cmcf->phases[NGX_HTTP_REWRITE_PHASE].type = NGX_OK; + /* the special find config phase for single handler */ + ngx_init_array(cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers, cf->cycle->pool, 1, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); @@ -241,6 +243,12 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *h = ngx_http_find_location_config; + ngx_init_array(cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, + cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), + NGX_CONF_ERROR); + cmcf->phases[NGX_HTTP_ACCESS_PHASE].type = NGX_DECLINED; + + ngx_init_array(cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 84617e2d4..d04d4f907 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -20,8 +20,12 @@ typedef struct { typedef enum { NGX_HTTP_REWRITE_PHASE = 0, + NGX_HTTP_FIND_CONFIG_PHASE, + + NGX_HTTP_ACCESS_PHASE, NGX_HTTP_CONTENT_PHASE, + NGX_HTTP_LAST_PHASE } ngx_http_phases; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index d1ed4f3a4..6a7f7c32a 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -159,10 +159,12 @@ static void ngx_http_init_request(ngx_event_t *rev) ngx_http_close_connection(c); return; } + + c->data = r; } + c->sent = 0; r->signature = NGX_HTTP_MODULE; - r->http_state = NGX_HTTP_INITING_REQUEST_STATE; /* find the server configuration for the address:port */ @@ -288,8 +290,6 @@ static void ngx_http_init_request(ngx_event_t *rev) return; } - c->sent = 0; - c->data = r; r->connection = c; r->pipeline = c->pipeline; r->header_in = c->buffer; @@ -301,6 +301,8 @@ static void ngx_http_init_request(ngx_event_t *rev) r->headers_out.content_length_n = -1; r->headers_out.last_modified_time = -1; + r->http_state = NGX_HTTP_READING_REQUEST_STATE; + rev->event_handler = ngx_http_process_request_line; ngx_http_process_request_line(rev); } @@ -711,6 +713,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http header done"); + r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; + rc = ngx_http_process_request_header(r); if (rc != NGX_OK) { @@ -1055,6 +1059,8 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r) return; } + r->http_state = NGX_HTTP_WRITING_REQUEST_STATE; + clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, ngx_http_core_module); if (!wev->delayed) { diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c index 2b18c0b1f..93a2cdb3b 100644 --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -15,6 +15,8 @@ sig_atomic_t ngx_timer; ngx_uint_t ngx_process; ngx_pid_t ngx_pid; ngx_uint_t ngx_threaded; +ngx_uint_t ngx_inherited; + sig_atomic_t ngx_terminate; sig_atomic_t ngx_quit;