mirror of
https://github.com/nginx/nginx.git
synced 2025-06-21 21:31:05 +08:00
Geo: IPv6 support.
The "ranges" mode is still limited to IPv4 only.
This commit is contained in:
parent
dd46cc659a
commit
3d87688bc6
@ -263,6 +263,203 @@ ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
|
||||||
|
uintptr_t value)
|
||||||
|
{
|
||||||
|
u_char bit;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_radix_node_t *node, *next;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
bit = 0x80;
|
||||||
|
|
||||||
|
node = tree->root;
|
||||||
|
next = tree->root;
|
||||||
|
|
||||||
|
while (bit & mask[i]) {
|
||||||
|
if (key[i] & bit) {
|
||||||
|
next = node->right;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
next = node->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit >>= 1;
|
||||||
|
node = next;
|
||||||
|
|
||||||
|
if (bit == 0) {
|
||||||
|
if (++i == 16) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
||||||
|
return NGX_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->value = value;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bit & mask[i]) {
|
||||||
|
next = ngx_radix_alloc(tree);
|
||||||
|
if (next == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
next->right = NULL;
|
||||||
|
next->left = NULL;
|
||||||
|
next->parent = node;
|
||||||
|
next->value = NGX_RADIX_NO_VALUE;
|
||||||
|
|
||||||
|
if (key[i] & bit) {
|
||||||
|
node->right = next;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
node->left = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit >>= 1;
|
||||||
|
node = next;
|
||||||
|
|
||||||
|
if (bit == 0) {
|
||||||
|
if (++i == 16) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node->value = value;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
|
||||||
|
{
|
||||||
|
u_char bit;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_radix_node_t *node;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
bit = 0x80;
|
||||||
|
node = tree->root;
|
||||||
|
|
||||||
|
while (node && (bit & mask[i])) {
|
||||||
|
if (key[i] & bit) {
|
||||||
|
node = node->right;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
node = node->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit >>= 1;
|
||||||
|
|
||||||
|
if (bit == 0) {
|
||||||
|
if (++i == 16) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->right || node->left) {
|
||||||
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
||||||
|
node->value = NGX_RADIX_NO_VALUE;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
if (node->parent->right == node) {
|
||||||
|
node->parent->right = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
node->parent->left = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->right = tree->free;
|
||||||
|
tree->free = node;
|
||||||
|
|
||||||
|
node = node->parent;
|
||||||
|
|
||||||
|
if (node->right || node->left) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->parent == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uintptr_t
|
||||||
|
ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
|
||||||
|
{
|
||||||
|
u_char bit;
|
||||||
|
uintptr_t value;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_radix_node_t *node;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
bit = 0x80;
|
||||||
|
value = NGX_RADIX_NO_VALUE;
|
||||||
|
node = tree->root;
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
||||||
|
value = node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key[i] & bit) {
|
||||||
|
node = node->right;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
node = node->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit >>= 1;
|
||||||
|
|
||||||
|
if (bit == 0) {
|
||||||
|
i++;
|
||||||
|
bit = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static ngx_radix_node_t *
|
static ngx_radix_node_t *
|
||||||
ngx_radix_alloc(ngx_radix_tree_t *tree)
|
ngx_radix_alloc(ngx_radix_tree_t *tree)
|
||||||
{
|
{
|
||||||
|
@ -36,11 +36,20 @@ typedef struct {
|
|||||||
|
|
||||||
ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool,
|
ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool,
|
||||||
ngx_int_t preallocate);
|
ngx_int_t preallocate);
|
||||||
|
|
||||||
ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
|
ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
|
||||||
uint32_t key, uint32_t mask, uintptr_t value);
|
uint32_t key, uint32_t mask, uintptr_t value);
|
||||||
ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
|
ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
|
||||||
uint32_t key, uint32_t mask);
|
uint32_t key, uint32_t mask);
|
||||||
uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key);
|
uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key);
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_int_t ngx_radix128tree_insert(ngx_radix_tree_t *tree,
|
||||||
|
u_char *key, u_char *mask, uintptr_t value);
|
||||||
|
ngx_int_t ngx_radix128tree_delete(ngx_radix_tree_t *tree,
|
||||||
|
u_char *key, u_char *mask);
|
||||||
|
uintptr_t ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_RADIX_TREE_H_INCLUDED_ */
|
#endif /* _NGX_RADIX_TREE_H_INCLUDED_ */
|
||||||
|
@ -17,6 +17,14 @@ typedef struct {
|
|||||||
} ngx_http_geo_range_t;
|
} ngx_http_geo_range_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_radix_tree_t *tree;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_radix_tree_t *tree6;
|
||||||
|
#endif
|
||||||
|
} ngx_http_geo_trees_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_http_geo_range_t **low;
|
ngx_http_geo_range_t **low;
|
||||||
ngx_http_variable_value_t *default_value;
|
ngx_http_variable_value_t *default_value;
|
||||||
@ -35,6 +43,9 @@ typedef struct {
|
|||||||
ngx_str_t *net;
|
ngx_str_t *net;
|
||||||
ngx_http_geo_high_ranges_t high;
|
ngx_http_geo_high_ranges_t high;
|
||||||
ngx_radix_tree_t *tree;
|
ngx_radix_tree_t *tree;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_radix_tree_t *tree6;
|
||||||
|
#endif
|
||||||
ngx_rbtree_t rbtree;
|
ngx_rbtree_t rbtree;
|
||||||
ngx_rbtree_node_t sentinel;
|
ngx_rbtree_node_t sentinel;
|
||||||
ngx_array_t *proxies;
|
ngx_array_t *proxies;
|
||||||
@ -57,7 +68,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
ngx_radix_tree_t *tree;
|
ngx_http_geo_trees_t trees;
|
||||||
ngx_http_geo_high_ranges_t high;
|
ngx_http_geo_high_ranges_t high;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
@ -68,8 +79,8 @@ typedef struct {
|
|||||||
} ngx_http_geo_ctx_t;
|
} ngx_http_geo_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r,
|
||||||
ngx_http_geo_ctx_t *ctx);
|
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
|
||||||
static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
|
||||||
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
|
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
|
||||||
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
@ -155,7 +166,7 @@ static ngx_http_geo_header_t ngx_http_geo_header = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* AF_INET only */
|
/* geo range is AF_INET only */
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
@ -163,10 +174,56 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||||||
{
|
{
|
||||||
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
||||||
|
|
||||||
|
in_addr_t inaddr;
|
||||||
|
ngx_addr_t addr;
|
||||||
|
struct sockaddr_in *sin;
|
||||||
ngx_http_variable_value_t *vv;
|
ngx_http_variable_value_t *vv;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
u_char *p;
|
||||||
|
struct in6_addr *inaddr6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) {
|
||||||
|
vv = (ngx_http_variable_value_t *)
|
||||||
|
ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
|
||||||
|
p = inaddr6->s6_addr;
|
||||||
|
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
|
||||||
|
inaddr = p[12] << 24;
|
||||||
|
inaddr += p[13] << 16;
|
||||||
|
inaddr += p[14] << 8;
|
||||||
|
inaddr += p[15];
|
||||||
|
|
||||||
vv = (ngx_http_variable_value_t *)
|
vv = (ngx_http_variable_value_t *)
|
||||||
ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
|
ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
vv = (ngx_http_variable_value_t *)
|
||||||
|
ngx_radix128tree_find(ctx->u.trees.tree6, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
sin = (struct sockaddr_in *) addr.sockaddr;
|
||||||
|
inaddr = ntohl(sin->sin_addr.s_addr);
|
||||||
|
|
||||||
|
vv = (ngx_http_variable_value_t *)
|
||||||
|
ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
*v = *vv;
|
*v = *vv;
|
||||||
|
|
||||||
@ -183,19 +240,56 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||||||
{
|
{
|
||||||
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
|
||||||
|
|
||||||
in_addr_t addr;
|
in_addr_t inaddr;
|
||||||
|
ngx_addr_t addr;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
struct sockaddr_in *sin;
|
||||||
ngx_http_geo_range_t *range;
|
ngx_http_geo_range_t *range;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
u_char *p;
|
||||||
|
struct in6_addr *inaddr6;
|
||||||
|
#endif
|
||||||
|
|
||||||
*v = *ctx->u.high.default_value;
|
*v = *ctx->u.high.default_value;
|
||||||
|
|
||||||
if (ctx->u.high.low) {
|
if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
|
||||||
addr = ngx_http_geo_addr(r, ctx);
|
|
||||||
|
|
||||||
range = ctx->u.high.low[addr >> 16];
|
switch (addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
|
||||||
|
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
|
||||||
|
p = inaddr6->s6_addr;
|
||||||
|
|
||||||
|
inaddr = p[12] << 24;
|
||||||
|
inaddr += p[13] << 16;
|
||||||
|
inaddr += p[14] << 8;
|
||||||
|
inaddr += p[15];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
inaddr = INADDR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
sin = (struct sockaddr_in *) addr.sockaddr;
|
||||||
|
inaddr = ntohl(sin->sin_addr.s_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
inaddr = INADDR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->u.high.low) {
|
||||||
|
range = ctx->u.high.low[inaddr >> 16];
|
||||||
|
|
||||||
if (range) {
|
if (range) {
|
||||||
n = addr & 0xffff;
|
n = inaddr & 0xffff;
|
||||||
do {
|
do {
|
||||||
if (n >= (ngx_uint_t) range->start
|
if (n >= (ngx_uint_t) range->start
|
||||||
&& n <= (ngx_uint_t) range->end)
|
&& n <= (ngx_uint_t) range->end)
|
||||||
@ -214,54 +308,25 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static in_addr_t
|
static ngx_int_t
|
||||||
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
|
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
|
||||||
|
ngx_addr_t *addr)
|
||||||
{
|
{
|
||||||
ngx_addr_t addr;
|
|
||||||
ngx_table_elt_t *xfwd;
|
ngx_table_elt_t *xfwd;
|
||||||
struct sockaddr_in *sin;
|
|
||||||
|
|
||||||
if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) {
|
if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
|
||||||
return INADDR_NONE;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfwd = r->headers_in.x_forwarded_for;
|
xfwd = r->headers_in.x_forwarded_for;
|
||||||
|
|
||||||
if (xfwd != NULL && ctx->proxies != NULL) {
|
if (xfwd != NULL && ctx->proxies != NULL) {
|
||||||
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
|
(void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
|
||||||
xfwd->value.len, ctx->proxies,
|
xfwd->value.len, ctx->proxies,
|
||||||
ctx->proxy_recursive);
|
ctx->proxy_recursive);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
return NGX_OK;
|
||||||
|
|
||||||
if (addr.sockaddr->sa_family == AF_INET6) {
|
|
||||||
u_char *p;
|
|
||||||
in_addr_t inaddr;
|
|
||||||
struct in6_addr *inaddr6;
|
|
||||||
|
|
||||||
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
|
|
||||||
|
|
||||||
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
|
|
||||||
p = inaddr6->s6_addr;
|
|
||||||
|
|
||||||
inaddr = p[12] << 24;
|
|
||||||
inaddr += p[13] << 16;
|
|
||||||
inaddr += p[14] << 8;
|
|
||||||
inaddr += p[15];
|
|
||||||
|
|
||||||
return inaddr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (addr.sockaddr->sa_family != AF_INET) {
|
|
||||||
return INADDR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
sin = (struct sockaddr_in *) addr.sockaddr;
|
|
||||||
return ntohl(sin->sin_addr.s_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -315,6 +380,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
ngx_http_variable_t *var;
|
ngx_http_variable_t *var;
|
||||||
ngx_http_geo_ctx_t *geo;
|
ngx_http_geo_ctx_t *geo;
|
||||||
ngx_http_geo_conf_ctx_t ctx;
|
ngx_http_geo_conf_ctx_t ctx;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
static struct in6_addr zero;
|
||||||
|
#endif
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
@ -445,7 +513,18 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geo->u.tree = ctx.tree;
|
geo->u.trees.tree = ctx.tree;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
if (ctx.tree6 == NULL) {
|
||||||
|
ctx.tree6 = ngx_radix_tree_create(cf->pool, -1);
|
||||||
|
if (ctx.tree6 == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
geo->u.trees.tree6 = ctx.tree6;
|
||||||
|
#endif
|
||||||
|
|
||||||
var->get_handler = ngx_http_geo_cidr_variable;
|
var->get_handler = ngx_http_geo_cidr_variable;
|
||||||
var->data = (uintptr_t) geo;
|
var->data = (uintptr_t) geo;
|
||||||
@ -461,6 +540,15 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NGX_BUSY is okay (default was set explicitly) */
|
/* NGX_BUSY is okay (default was set explicitly) */
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
|
||||||
|
(uintptr_t) &ngx_http_variable_null_value)
|
||||||
|
== NGX_ERROR)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
@ -483,7 +571,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
|||||||
|
|
||||||
if (ngx_strcmp(value[0].data, "ranges") == 0) {
|
if (ngx_strcmp(value[0].data, "ranges") == 0) {
|
||||||
|
|
||||||
if (ctx->tree) {
|
if (ctx->tree
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|| ctx->tree6
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"the \"ranges\" directive must be "
|
"the \"ranges\" directive must be "
|
||||||
"the first directive inside \"geo\" block");
|
"the first directive inside \"geo\" block");
|
||||||
@ -934,6 +1027,15 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
if (ctx->tree6 == NULL) {
|
||||||
|
ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1);
|
||||||
|
if (ctx->tree6 == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ngx_strcmp(value[0].data, "default") == 0) {
|
if (ngx_strcmp(value[0].data, "default") == 0) {
|
||||||
/* cidr.family = AF_INET; */
|
/* cidr.family = AF_INET; */
|
||||||
cidr.u.in.addr = 0;
|
cidr.u.in.addr = 0;
|
||||||
@ -954,20 +1056,29 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cidr.family != AF_INET) {
|
if (cidr.family == AF_INET) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"\"geo\" supports IPv4 only");
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cidr.u.in.addr = ntohl(cidr.u.in.addr);
|
cidr.u.in.addr = ntohl(cidr.u.in.addr);
|
||||||
cidr.u.in.mask = ntohl(cidr.u.in.mask);
|
cidr.u.in.mask = ntohl(cidr.u.in.mask);
|
||||||
|
}
|
||||||
|
|
||||||
if (del) {
|
if (del) {
|
||||||
if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
|
switch (cidr.family) {
|
||||||
cidr.u.in.mask)
|
|
||||||
!= NGX_OK)
|
#if (NGX_HAVE_INET6)
|
||||||
{
|
case AF_INET6:
|
||||||
|
rc = ngx_radix128tree_delete(ctx->tree6,
|
||||||
|
cidr.u.in6.addr.s6_addr,
|
||||||
|
cidr.u.in6.mask.s6_addr);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
|
||||||
|
cidr.u.in.mask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
"no network \"%V\" to delete", net);
|
"no network \"%V\" to delete", net);
|
||||||
}
|
}
|
||||||
@ -982,9 +1093,51 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (cidr.family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
for (i = 2; i; i--) {
|
for (i = 2; i; i--) {
|
||||||
rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
|
rc = ngx_radix128tree_insert(ctx->tree6, cidr.u.in6.addr.s6_addr,
|
||||||
|
cidr.u.in6.mask.s6_addr,
|
||||||
(uintptr_t) val);
|
(uintptr_t) val);
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rc == NGX_BUSY */
|
||||||
|
|
||||||
|
old = (ngx_http_variable_value_t *)
|
||||||
|
ngx_radix128tree_find(ctx->tree6,
|
||||||
|
cidr.u.in6.addr.s6_addr);
|
||||||
|
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
|
||||||
|
net, val, old);
|
||||||
|
|
||||||
|
rc = ngx_radix128tree_delete(ctx->tree6,
|
||||||
|
cidr.u.in6.addr.s6_addr,
|
||||||
|
cidr.u.in6.mask.s6_addr);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
for (i = 2; i; i--) {
|
||||||
|
rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr,
|
||||||
|
cidr.u.in.mask, (uintptr_t) val);
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
if (rc == NGX_OK) {
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
@ -1002,7 +1155,8 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
|||||||
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
|
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
|
||||||
net, val, old);
|
net, val, old);
|
||||||
|
|
||||||
rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
|
rc = ngx_radix32tree_delete(ctx->tree,
|
||||||
|
cidr.u.in.addr, cidr.u.in.mask);
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
if (rc == NGX_ERROR) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
|
||||||
@ -1010,6 +1164,9 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user