mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
$geo variable support
This commit is contained in:
parent
976603a646
commit
9a1d46684c
@ -40,6 +40,18 @@ typedef struct {
|
||||
} ngx_http_geo_conf_ctx_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
ngx_radix_tree_t *tree;
|
||||
ngx_http_geo_high_ranges_t *high;
|
||||
} u;
|
||||
|
||||
ngx_int_t index;
|
||||
} ngx_http_geo_ctx_t;
|
||||
|
||||
|
||||
static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
|
||||
ngx_http_geo_ctx_t *ctx);
|
||||
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
|
||||
static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
||||
@ -57,7 +69,7 @@ static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
|
||||
static ngx_command_t ngx_http_geo_commands[] = {
|
||||
|
||||
{ ngx_string("geo"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
|
||||
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
|
||||
ngx_http_geo_block,
|
||||
NGX_HTTP_MAIN_CONF_OFFSET,
|
||||
0,
|
||||
@ -104,23 +116,17 @@ static ngx_int_t
|
||||
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||
uintptr_t data)
|
||||
{
|
||||
ngx_radix_tree_t *tree = (ngx_radix_tree_t *) data;
|
||||
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
||||
|
||||
struct sockaddr_in *sin;
|
||||
ngx_http_variable_value_t *vv;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo started");
|
||||
|
||||
sin = (struct sockaddr_in *) r->connection->sockaddr;
|
||||
|
||||
vv = (ngx_http_variable_value_t *)
|
||||
ngx_radix32tree_find(tree, ntohl(sin->sin_addr.s_addr));
|
||||
ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
|
||||
|
||||
*v = *vv;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo: %V %v", &r->connection->addr_text, v);
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo: %v", v);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
@ -130,27 +136,21 @@ static ngx_int_t
|
||||
ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||
uintptr_t data)
|
||||
{
|
||||
ngx_http_geo_high_ranges_t *high = (ngx_http_geo_high_ranges_t *) data;
|
||||
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
||||
|
||||
in_addr_t addr;
|
||||
ngx_uint_t i, n;
|
||||
struct sockaddr_in *sin;
|
||||
ngx_http_geo_range_t *range;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo started");
|
||||
*v = *ctx->u.high->default_value;
|
||||
|
||||
sin = (struct sockaddr_in *) r->connection->sockaddr;
|
||||
addr = ngx_http_geo_addr(r, ctx);
|
||||
|
||||
*v = *high->default_value;
|
||||
|
||||
addr = ntohl(sin->sin_addr.s_addr);
|
||||
|
||||
range = high->low[addr >> 16].ranges;
|
||||
range = ctx->u.high->low[addr >> 16].ranges;
|
||||
|
||||
n = addr & 0xffff;
|
||||
|
||||
for (i = 0; i < high->low[addr >> 16].n; i++) {
|
||||
for (i = 0; i < ctx->u.high->low[addr >> 16].n; i++) {
|
||||
if (n >= (ngx_uint_t) range[i].start
|
||||
&& n <= (ngx_uint_t) range[i].end)
|
||||
{
|
||||
@ -158,29 +158,84 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo: %V %v", &r->connection->addr_text, v);
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo: %v", v);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static in_addr_t
|
||||
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
ngx_http_variable_value_t *v;
|
||||
|
||||
if (ctx->index == -1) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo started: %V", &r->connection->addr_text);
|
||||
|
||||
sin = (struct sockaddr_in *) r->connection->sockaddr;
|
||||
return ntohl(sin->sin_addr.s_addr);
|
||||
}
|
||||
|
||||
v = ngx_http_get_flushed_variable(r, ctx->index);
|
||||
|
||||
if (v == NULL || v->not_found) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo not found");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http geo started: %v", v);
|
||||
|
||||
return ntohl(ngx_inet_addr(v->data, v->len));
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
char *rv;
|
||||
size_t len;
|
||||
ngx_str_t *value;
|
||||
ngx_str_t *value, name;
|
||||
ngx_uint_t i;
|
||||
ngx_conf_t save;
|
||||
ngx_pool_t *pool;
|
||||
ngx_array_t *a;
|
||||
ngx_http_variable_t *var;
|
||||
ngx_http_geo_ctx_t *geo;
|
||||
ngx_http_geo_conf_ctx_t ctx;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
var = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
|
||||
geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t));
|
||||
if (geo == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
name = value[1];
|
||||
name.len--;
|
||||
name.data++;
|
||||
|
||||
if (cf->args->nelts == 3) {
|
||||
|
||||
geo->index = ngx_http_get_variable_index(cf, &name);
|
||||
if (geo->index == NGX_ERROR) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
name = value[2];
|
||||
name.len--;
|
||||
name.data++;
|
||||
|
||||
} else {
|
||||
geo->index = -1;
|
||||
}
|
||||
|
||||
var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
|
||||
if (var == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
@ -233,8 +288,10 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_memcpy(ctx.high->low[i].ranges, a->elts, len);
|
||||
}
|
||||
|
||||
geo->u.high = ctx.high;
|
||||
|
||||
var->get_handler = ngx_http_geo_range_variable;
|
||||
var->data = (uintptr_t) ctx.high;
|
||||
var->data = (uintptr_t) geo;
|
||||
|
||||
ngx_destroy_pool(ctx.temp_pool);
|
||||
ngx_destroy_pool(pool);
|
||||
@ -251,8 +308,10 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
}
|
||||
|
||||
geo->u.tree = ctx.tree;
|
||||
|
||||
var->get_handler = ngx_http_geo_cidr_variable;
|
||||
var->data = (uintptr_t) ctx.tree;
|
||||
var->data = (uintptr_t) geo;
|
||||
|
||||
ngx_destroy_pool(ctx.temp_pool);
|
||||
ngx_destroy_pool(pool);
|
||||
@ -633,6 +692,11 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
||||
del = 0;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
|
||||
cidrin.addr = 0xffffffff;
|
||||
cidrin.mask = 0xffffffff;
|
||||
|
||||
} else {
|
||||
rc = ngx_ptocidr(net, &cidrin);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
@ -643,11 +707,13 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
||||
|
||||
if (rc == NGX_DONE) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"low address bits of %V are meaningless", net);
|
||||
"low address bits of %V are meaningless",
|
||||
net);
|
||||
}
|
||||
|
||||
cidrin.addr = ntohl(cidrin.addr);
|
||||
cidrin.mask = ntohl(cidrin.mask);
|
||||
}
|
||||
|
||||
if (del) {
|
||||
if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask)
|
||||
|
Loading…
Reference in New Issue
Block a user