Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_geo_module.c @ 694:88a1b4797f2e NGINX_1_3_10
nginx 1.3.10
*) Change: domain names specified in configuration file are now resolved
to IPv6 addresses as well as IPv4 ones.
*) Change: now if the "include" directive with mask is used on Unix
systems, included files are sorted in alphabetical order.
*) Change: the "add_header" directive adds headers to 201 responses.
*) Feature: the "geo" directive now supports IPv6 addresses in CIDR
notation.
*) Feature: the "flush" and "gzip" parameters of the "access_log"
directive.
*) Feature: variables support in the "auth_basic" directive.
*) Bugfix: nginx could not be built with the ngx_http_perl_module in
some cases.
*) Bugfix: a segmentation fault might occur in a worker process if the
ngx_http_xslt_module was used.
*) Bugfix: nginx could not be built on MacOSX in some cases.
Thanks to Piotr Sikora.
*) Bugfix: the "limit_rate" directive with high rates might result in
truncated responses on 32-bit platforms.
Thanks to Alexey Antropov.
*) Bugfix: a segmentation fault might occur in a worker process if the
"if" directive was used.
Thanks to Piotr Sikora.
*) Bugfix: a "100 Continue" response was issued with "413 Request Entity
Too Large" responses.
*) Bugfix: the "image_filter", "image_filter_jpeg_quality" and
"image_filter_sharpen" directives might be inherited incorrectly.
Thanks to Ian Babrou.
*) Bugfix: "crypt_r() failed" errors might appear if the "auth_basic"
directive was used on Linux.
*) Bugfix: in backup servers handling.
Thanks to Thomas Chen.
*) Bugfix: proxied HEAD requests might return incorrect response if the
"gzip" directive was used.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 25 Dec 2012 00:00:00 +0400 |
parents | 2e8a942c8872 |
children |
comparison
equal
deleted
inserted
replaced
693:cfd4279acc6e | 694:88a1b4797f2e |
---|---|
16 u_short end; | 16 u_short end; |
17 } ngx_http_geo_range_t; | 17 } ngx_http_geo_range_t; |
18 | 18 |
19 | 19 |
20 typedef struct { | 20 typedef struct { |
21 ngx_radix_tree_t *tree; | |
22 #if (NGX_HAVE_INET6) | |
23 ngx_radix_tree_t *tree6; | |
24 #endif | |
25 } ngx_http_geo_trees_t; | |
26 | |
27 | |
28 typedef struct { | |
21 ngx_http_geo_range_t **low; | 29 ngx_http_geo_range_t **low; |
22 ngx_http_variable_value_t *default_value; | 30 ngx_http_variable_value_t *default_value; |
23 } ngx_http_geo_high_ranges_t; | 31 } ngx_http_geo_high_ranges_t; |
24 | 32 |
25 | 33 |
33 typedef struct { | 41 typedef struct { |
34 ngx_http_variable_value_t *value; | 42 ngx_http_variable_value_t *value; |
35 ngx_str_t *net; | 43 ngx_str_t *net; |
36 ngx_http_geo_high_ranges_t high; | 44 ngx_http_geo_high_ranges_t high; |
37 ngx_radix_tree_t *tree; | 45 ngx_radix_tree_t *tree; |
46 #if (NGX_HAVE_INET6) | |
47 ngx_radix_tree_t *tree6; | |
48 #endif | |
38 ngx_rbtree_t rbtree; | 49 ngx_rbtree_t rbtree; |
39 ngx_rbtree_node_t sentinel; | 50 ngx_rbtree_node_t sentinel; |
40 ngx_array_t *proxies; | 51 ngx_array_t *proxies; |
41 ngx_pool_t *pool; | 52 ngx_pool_t *pool; |
42 ngx_pool_t *temp_pool; | 53 ngx_pool_t *temp_pool; |
55 } ngx_http_geo_conf_ctx_t; | 66 } ngx_http_geo_conf_ctx_t; |
56 | 67 |
57 | 68 |
58 typedef struct { | 69 typedef struct { |
59 union { | 70 union { |
60 ngx_radix_tree_t *tree; | 71 ngx_http_geo_trees_t trees; |
61 ngx_http_geo_high_ranges_t high; | 72 ngx_http_geo_high_ranges_t high; |
62 } u; | 73 } u; |
63 | 74 |
64 ngx_array_t *proxies; | 75 ngx_array_t *proxies; |
65 unsigned proxy_recursive:1; | 76 unsigned proxy_recursive:1; |
66 | 77 |
67 ngx_int_t index; | 78 ngx_int_t index; |
68 } ngx_http_geo_ctx_t; | 79 } ngx_http_geo_ctx_t; |
69 | 80 |
70 | 81 |
71 static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r, | 82 static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r, |
72 ngx_http_geo_ctx_t *ctx); | 83 ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr); |
73 static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r, | 84 static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r, |
74 ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr); | 85 ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr); |
75 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 86 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
76 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); | 87 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); |
77 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, | 88 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, |
153 static ngx_http_geo_header_t ngx_http_geo_header = { | 164 static ngx_http_geo_header_t ngx_http_geo_header = { |
154 { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0 | 165 { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0 |
155 }; | 166 }; |
156 | 167 |
157 | 168 |
158 /* AF_INET only */ | 169 /* geo range is AF_INET only */ |
159 | 170 |
160 static ngx_int_t | 171 static ngx_int_t |
161 ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | 172 ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
162 uintptr_t data) | 173 uintptr_t data) |
163 { | 174 { |
164 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; | 175 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; |
165 | 176 |
177 in_addr_t inaddr; | |
178 ngx_addr_t addr; | |
179 struct sockaddr_in *sin; | |
166 ngx_http_variable_value_t *vv; | 180 ngx_http_variable_value_t *vv; |
167 | 181 #if (NGX_HAVE_INET6) |
168 vv = (ngx_http_variable_value_t *) | 182 u_char *p; |
169 ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx)); | 183 struct in6_addr *inaddr6; |
184 #endif | |
185 | |
186 if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) { | |
187 vv = (ngx_http_variable_value_t *) | |
188 ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE); | |
189 goto done; | |
190 } | |
191 | |
192 switch (addr.sockaddr->sa_family) { | |
193 | |
194 #if (NGX_HAVE_INET6) | |
195 case AF_INET6: | |
196 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; | |
197 p = inaddr6->s6_addr; | |
198 | |
199 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { | |
200 inaddr = p[12] << 24; | |
201 inaddr += p[13] << 16; | |
202 inaddr += p[14] << 8; | |
203 inaddr += p[15]; | |
204 | |
205 vv = (ngx_http_variable_value_t *) | |
206 ngx_radix32tree_find(ctx->u.trees.tree, inaddr); | |
207 | |
208 } else { | |
209 vv = (ngx_http_variable_value_t *) | |
210 ngx_radix128tree_find(ctx->u.trees.tree6, p); | |
211 } | |
212 | |
213 break; | |
214 #endif | |
215 | |
216 default: /* AF_INET */ | |
217 sin = (struct sockaddr_in *) addr.sockaddr; | |
218 inaddr = ntohl(sin->sin_addr.s_addr); | |
219 | |
220 vv = (ngx_http_variable_value_t *) | |
221 ngx_radix32tree_find(ctx->u.trees.tree, inaddr); | |
222 | |
223 break; | |
224 } | |
225 | |
226 done: | |
170 | 227 |
171 *v = *vv; | 228 *v = *vv; |
172 | 229 |
173 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 230 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
174 "http geo: %v", v); | 231 "http geo: %v", v); |
181 ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | 238 ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
182 uintptr_t data) | 239 uintptr_t data) |
183 { | 240 { |
184 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; | 241 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; |
185 | 242 |
186 in_addr_t addr; | 243 in_addr_t inaddr; |
244 ngx_addr_t addr; | |
187 ngx_uint_t n; | 245 ngx_uint_t n; |
246 struct sockaddr_in *sin; | |
188 ngx_http_geo_range_t *range; | 247 ngx_http_geo_range_t *range; |
248 #if (NGX_HAVE_INET6) | |
249 u_char *p; | |
250 struct in6_addr *inaddr6; | |
251 #endif | |
189 | 252 |
190 *v = *ctx->u.high.default_value; | 253 *v = *ctx->u.high.default_value; |
191 | 254 |
192 addr = ngx_http_geo_addr(r, ctx); | 255 if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) { |
193 | 256 |
194 range = ctx->u.high.low[addr >> 16]; | 257 switch (addr.sockaddr->sa_family) { |
195 | 258 |
196 if (range) { | 259 #if (NGX_HAVE_INET6) |
197 n = addr & 0xffff; | 260 case AF_INET6: |
198 do { | 261 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; |
199 if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end) | 262 |
200 { | 263 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { |
201 *v = *range->value; | 264 p = inaddr6->s6_addr; |
202 break; | 265 |
203 } | 266 inaddr = p[12] << 24; |
204 } while ((++range)->value); | 267 inaddr += p[13] << 16; |
268 inaddr += p[14] << 8; | |
269 inaddr += p[15]; | |
270 | |
271 } else { | |
272 inaddr = INADDR_NONE; | |
273 } | |
274 | |
275 break; | |
276 #endif | |
277 | |
278 default: /* AF_INET */ | |
279 sin = (struct sockaddr_in *) addr.sockaddr; | |
280 inaddr = ntohl(sin->sin_addr.s_addr); | |
281 break; | |
282 } | |
283 | |
284 } else { | |
285 inaddr = INADDR_NONE; | |
286 } | |
287 | |
288 if (ctx->u.high.low) { | |
289 range = ctx->u.high.low[inaddr >> 16]; | |
290 | |
291 if (range) { | |
292 n = inaddr & 0xffff; | |
293 do { | |
294 if (n >= (ngx_uint_t) range->start | |
295 && n <= (ngx_uint_t) range->end) | |
296 { | |
297 *v = *range->value; | |
298 break; | |
299 } | |
300 } while ((++range)->value); | |
301 } | |
205 } | 302 } |
206 | 303 |
207 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 304 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
208 "http geo: %v", v); | 305 "http geo: %v", v); |
209 | 306 |
210 return NGX_OK; | 307 return NGX_OK; |
211 } | 308 } |
212 | 309 |
213 | 310 |
214 static in_addr_t | 311 static ngx_int_t |
215 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) | 312 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx, |
313 ngx_addr_t *addr) | |
216 { | 314 { |
217 ngx_addr_t addr; | 315 ngx_table_elt_t *xfwd; |
218 ngx_table_elt_t *xfwd; | 316 |
219 struct sockaddr_in *sin; | 317 if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) { |
220 | 318 return NGX_ERROR; |
221 if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) { | |
222 return INADDR_NONE; | |
223 } | 319 } |
224 | 320 |
225 xfwd = r->headers_in.x_forwarded_for; | 321 xfwd = r->headers_in.x_forwarded_for; |
226 | 322 |
227 if (xfwd != NULL && ctx->proxies != NULL) { | 323 if (xfwd != NULL && ctx->proxies != NULL) { |
228 (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data, | 324 (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data, |
229 xfwd->value.len, ctx->proxies, | 325 xfwd->value.len, ctx->proxies, |
230 ctx->proxy_recursive); | 326 ctx->proxy_recursive); |
231 } | 327 } |
232 | 328 |
233 #if (NGX_HAVE_INET6) | 329 return NGX_OK; |
234 | |
235 if (addr.sockaddr->sa_family == AF_INET6) { | |
236 u_char *p; | |
237 in_addr_t inaddr; | |
238 struct in6_addr *inaddr6; | |
239 | |
240 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; | |
241 | |
242 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { | |
243 p = inaddr6->s6_addr; | |
244 | |
245 inaddr = p[12] << 24; | |
246 inaddr += p[13] << 16; | |
247 inaddr += p[14] << 8; | |
248 inaddr += p[15]; | |
249 | |
250 return inaddr; | |
251 } | |
252 } | |
253 | |
254 #endif | |
255 | |
256 if (addr.sockaddr->sa_family != AF_INET) { | |
257 return INADDR_NONE; | |
258 } | |
259 | |
260 sin = (struct sockaddr_in *) addr.sockaddr; | |
261 return ntohl(sin->sin_addr.s_addr); | |
262 } | 330 } |
263 | 331 |
264 | 332 |
265 static ngx_int_t | 333 static ngx_int_t |
266 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx, | 334 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx, |
301 | 369 |
302 static char * | 370 static char * |
303 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 371 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
304 { | 372 { |
305 char *rv; | 373 char *rv; |
306 void **p; | |
307 size_t len; | 374 size_t len; |
308 ngx_str_t *value, name; | 375 ngx_str_t *value, name; |
309 ngx_uint_t i; | 376 ngx_uint_t i; |
310 ngx_conf_t save; | 377 ngx_conf_t save; |
311 ngx_pool_t *pool; | 378 ngx_pool_t *pool; |
312 ngx_array_t *a; | 379 ngx_array_t *a; |
313 ngx_http_variable_t *var; | 380 ngx_http_variable_t *var; |
314 ngx_http_geo_ctx_t *geo; | 381 ngx_http_geo_ctx_t *geo; |
315 ngx_http_geo_conf_ctx_t ctx; | 382 ngx_http_geo_conf_ctx_t ctx; |
383 #if (NGX_HAVE_INET6) | |
384 static struct in6_addr zero; | |
385 #endif | |
316 | 386 |
317 value = cf->args->elts; | 387 value = cf->args->elts; |
318 | 388 |
319 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t)); | 389 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t)); |
320 if (geo == NULL) { | 390 if (geo == NULL) { |
321 return NGX_CONF_ERROR; | 391 return NGX_CONF_ERROR; |
322 } | 392 } |
323 | 393 |
324 name = value[1]; | 394 name = value[1]; |
395 | |
396 if (name.data[0] != '$') { | |
397 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
398 "invalid variable name \"%V\"", &name); | |
399 return NGX_CONF_ERROR; | |
400 } | |
401 | |
325 name.len--; | 402 name.len--; |
326 name.data++; | 403 name.data++; |
327 | 404 |
328 if (cf->args->nelts == 3) { | 405 if (cf->args->nelts == 3) { |
329 | 406 |
331 if (geo->index == NGX_ERROR) { | 408 if (geo->index == NGX_ERROR) { |
332 return NGX_CONF_ERROR; | 409 return NGX_CONF_ERROR; |
333 } | 410 } |
334 | 411 |
335 name = value[2]; | 412 name = value[2]; |
413 | |
414 if (name.data[0] != '$') { | |
415 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
416 "invalid variable name \"%V\"", &name); | |
417 return NGX_CONF_ERROR; | |
418 } | |
419 | |
336 name.len--; | 420 name.len--; |
337 name.data++; | 421 name.data++; |
338 | 422 |
339 } else { | 423 } else { |
340 geo->index = -1; | 424 geo->index = -1; |
376 *cf = save; | 460 *cf = save; |
377 | 461 |
378 geo->proxies = ctx.proxies; | 462 geo->proxies = ctx.proxies; |
379 geo->proxy_recursive = ctx.proxy_recursive; | 463 geo->proxy_recursive = ctx.proxy_recursive; |
380 | 464 |
381 if (ctx.high.low) { | 465 if (ctx.ranges) { |
382 | 466 |
383 if (!ctx.binary_include) { | 467 if (ctx.high.low && !ctx.binary_include) { |
384 for (i = 0; i < 0x10000; i++) { | 468 for (i = 0; i < 0x10000; i++) { |
385 a = (ngx_array_t *) ctx.high.low[i]; | 469 a = (ngx_array_t *) ctx.high.low[i]; |
386 | 470 |
387 if (a == NULL || a->nelts == 0) { | 471 if (a == NULL || a->nelts == 0) { |
388 continue; | 472 continue; |
393 ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *)); | 477 ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *)); |
394 if (ctx.high.low[i] == NULL) { | 478 if (ctx.high.low[i] == NULL) { |
395 return NGX_CONF_ERROR; | 479 return NGX_CONF_ERROR; |
396 } | 480 } |
397 | 481 |
398 p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len); | 482 ngx_memcpy(ctx.high.low[i], a->elts, len); |
399 *p = NULL; | 483 ctx.high.low[i][a->nelts].value = NULL; |
400 ctx.data_size += len + sizeof(void *); | 484 ctx.data_size += len + sizeof(void *); |
401 } | 485 } |
402 | 486 |
403 if (ctx.allow_binary_include | 487 if (ctx.allow_binary_include |
404 && !ctx.outside_entries | 488 && !ctx.outside_entries |
427 if (ctx.tree == NULL) { | 511 if (ctx.tree == NULL) { |
428 return NGX_CONF_ERROR; | 512 return NGX_CONF_ERROR; |
429 } | 513 } |
430 } | 514 } |
431 | 515 |
432 geo->u.tree = ctx.tree; | 516 geo->u.trees.tree = ctx.tree; |
517 | |
518 #if (NGX_HAVE_INET6) | |
519 if (ctx.tree6 == NULL) { | |
520 ctx.tree6 = ngx_radix_tree_create(cf->pool, -1); | |
521 if (ctx.tree6 == NULL) { | |
522 return NGX_CONF_ERROR; | |
523 } | |
524 } | |
525 | |
526 geo->u.trees.tree6 = ctx.tree6; | |
527 #endif | |
433 | 528 |
434 var->get_handler = ngx_http_geo_cidr_variable; | 529 var->get_handler = ngx_http_geo_cidr_variable; |
435 var->data = (uintptr_t) geo; | 530 var->data = (uintptr_t) geo; |
436 | 531 |
437 ngx_destroy_pool(ctx.temp_pool); | 532 ngx_destroy_pool(ctx.temp_pool); |
438 ngx_destroy_pool(pool); | 533 ngx_destroy_pool(pool); |
439 | |
440 if (ngx_radix32tree_find(ctx.tree, 0) != NGX_RADIX_NO_VALUE) { | |
441 return rv; | |
442 } | |
443 | 534 |
444 if (ngx_radix32tree_insert(ctx.tree, 0, 0, | 535 if (ngx_radix32tree_insert(ctx.tree, 0, 0, |
445 (uintptr_t) &ngx_http_variable_null_value) | 536 (uintptr_t) &ngx_http_variable_null_value) |
446 == NGX_ERROR) | 537 == NGX_ERROR) |
447 { | 538 { |
448 return NGX_CONF_ERROR; | 539 return NGX_CONF_ERROR; |
449 } | 540 } |
541 | |
542 /* NGX_BUSY is okay (default was set explicitly) */ | |
543 | |
544 #if (NGX_HAVE_INET6) | |
545 if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr, | |
546 (uintptr_t) &ngx_http_variable_null_value) | |
547 == NGX_ERROR) | |
548 { | |
549 return NGX_CONF_ERROR; | |
550 } | |
551 #endif | |
450 } | 552 } |
451 | 553 |
452 return rv; | 554 return rv; |
453 } | 555 } |
454 | 556 |
467 | 569 |
468 if (cf->args->nelts == 1) { | 570 if (cf->args->nelts == 1) { |
469 | 571 |
470 if (ngx_strcmp(value[0].data, "ranges") == 0) { | 572 if (ngx_strcmp(value[0].data, "ranges") == 0) { |
471 | 573 |
472 if (ctx->tree) { | 574 if (ctx->tree |
575 #if (NGX_HAVE_INET6) | |
576 || ctx->tree6 | |
577 #endif | |
578 ) | |
579 { | |
473 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 580 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
474 "the \"ranges\" directive must be " | 581 "the \"ranges\" directive must be " |
475 "the first directive inside \"geo\" block"); | 582 "the first directive inside \"geo\" block"); |
476 goto failed; | 583 goto failed; |
477 } | 584 } |
918 if (ctx->tree == NULL) { | 1025 if (ctx->tree == NULL) { |
919 return NGX_CONF_ERROR; | 1026 return NGX_CONF_ERROR; |
920 } | 1027 } |
921 } | 1028 } |
922 | 1029 |
1030 #if (NGX_HAVE_INET6) | |
1031 if (ctx->tree6 == NULL) { | |
1032 ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1); | |
1033 if (ctx->tree6 == NULL) { | |
1034 return NGX_CONF_ERROR; | |
1035 } | |
1036 } | |
1037 #endif | |
1038 | |
923 if (ngx_strcmp(value[0].data, "default") == 0) { | 1039 if (ngx_strcmp(value[0].data, "default") == 0) { |
924 /* cidr.family = AF_INET; */ | 1040 cidr.family = AF_INET; |
925 cidr.u.in.addr = 0; | 1041 cidr.u.in.addr = 0; |
926 cidr.u.in.mask = 0; | 1042 cidr.u.in.mask = 0; |
927 net = &value[0]; | 1043 net = &value[0]; |
928 | 1044 |
929 } else { | 1045 } else { |
938 | 1054 |
939 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) { | 1055 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) { |
940 return NGX_CONF_ERROR; | 1056 return NGX_CONF_ERROR; |
941 } | 1057 } |
942 | 1058 |
943 if (cidr.family != AF_INET) { | 1059 if (cidr.family == AF_INET) { |
944 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1060 cidr.u.in.addr = ntohl(cidr.u.in.addr); |
945 "\"geo\" supports IPv4 only"); | 1061 cidr.u.in.mask = ntohl(cidr.u.in.mask); |
946 return NGX_CONF_ERROR; | 1062 } |
947 } | |
948 | |
949 cidr.u.in.addr = ntohl(cidr.u.in.addr); | |
950 cidr.u.in.mask = ntohl(cidr.u.in.mask); | |
951 | 1063 |
952 if (del) { | 1064 if (del) { |
953 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, | 1065 switch (cidr.family) { |
954 cidr.u.in.mask) | 1066 |
955 != NGX_OK) | 1067 #if (NGX_HAVE_INET6) |
956 { | 1068 case AF_INET6: |
1069 rc = ngx_radix128tree_delete(ctx->tree6, | |
1070 cidr.u.in6.addr.s6_addr, | |
1071 cidr.u.in6.mask.s6_addr); | |
1072 break; | |
1073 #endif | |
1074 | |
1075 default: /* AF_INET */ | |
1076 rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, | |
1077 cidr.u.in.mask); | |
1078 break; | |
1079 } | |
1080 | |
1081 if (rc != NGX_OK) { | |
957 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | 1082 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
958 "no network \"%V\" to delete", net); | 1083 "no network \"%V\" to delete", net); |
959 } | 1084 } |
960 | 1085 |
961 return NGX_CONF_OK; | 1086 return NGX_CONF_OK; |
966 | 1091 |
967 if (val == NULL) { | 1092 if (val == NULL) { |
968 return NGX_CONF_ERROR; | 1093 return NGX_CONF_ERROR; |
969 } | 1094 } |
970 | 1095 |
971 for (i = 2; i; i--) { | 1096 switch (cidr.family) { |
972 rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask, | 1097 |
973 (uintptr_t) val); | 1098 #if (NGX_HAVE_INET6) |
974 if (rc == NGX_OK) { | 1099 case AF_INET6: |
975 return NGX_CONF_OK; | 1100 for (i = 2; i; i--) { |
976 } | 1101 rc = ngx_radix128tree_insert(ctx->tree6, cidr.u.in6.addr.s6_addr, |
977 | 1102 cidr.u.in6.mask.s6_addr, |
978 if (rc == NGX_ERROR) { | 1103 (uintptr_t) val); |
979 return NGX_CONF_ERROR; | 1104 |
980 } | 1105 if (rc == NGX_OK) { |
981 | 1106 return NGX_CONF_OK; |
982 /* rc == NGX_BUSY */ | 1107 } |
983 | 1108 |
984 old = (ngx_http_variable_value_t *) | 1109 if (rc == NGX_ERROR) { |
985 ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask); | 1110 return NGX_CONF_ERROR; |
986 | 1111 } |
987 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | 1112 |
988 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", | 1113 /* rc == NGX_BUSY */ |
989 net, val, old); | 1114 |
990 | 1115 old = (ngx_http_variable_value_t *) |
991 rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask); | 1116 ngx_radix128tree_find(ctx->tree6, |
992 | 1117 cidr.u.in6.addr.s6_addr); |
993 if (rc == NGX_ERROR) { | 1118 |
994 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); | 1119 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
995 return NGX_CONF_ERROR; | 1120 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", |
996 } | 1121 net, val, old); |
1122 | |
1123 rc = ngx_radix128tree_delete(ctx->tree6, | |
1124 cidr.u.in6.addr.s6_addr, | |
1125 cidr.u.in6.mask.s6_addr); | |
1126 | |
1127 if (rc == NGX_ERROR) { | |
1128 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); | |
1129 return NGX_CONF_ERROR; | |
1130 } | |
1131 } | |
1132 | |
1133 break; | |
1134 #endif | |
1135 | |
1136 default: /* AF_INET */ | |
1137 for (i = 2; i; i--) { | |
1138 rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, | |
1139 cidr.u.in.mask, (uintptr_t) val); | |
1140 | |
1141 if (rc == NGX_OK) { | |
1142 return NGX_CONF_OK; | |
1143 } | |
1144 | |
1145 if (rc == NGX_ERROR) { | |
1146 return NGX_CONF_ERROR; | |
1147 } | |
1148 | |
1149 /* rc == NGX_BUSY */ | |
1150 | |
1151 old = (ngx_http_variable_value_t *) | |
1152 ngx_radix32tree_find(ctx->tree, cidr.u.in.addr); | |
1153 | |
1154 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
1155 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", | |
1156 net, val, old); | |
1157 | |
1158 rc = ngx_radix32tree_delete(ctx->tree, | |
1159 cidr.u.in.addr, cidr.u.in.mask); | |
1160 | |
1161 if (rc == NGX_ERROR) { | |
1162 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); | |
1163 return NGX_CONF_ERROR; | |
1164 } | |
1165 } | |
1166 | |
1167 break; | |
997 } | 1168 } |
998 | 1169 |
999 return NGX_CONF_ERROR; | 1170 return NGX_CONF_ERROR; |
1000 } | 1171 } |
1001 | 1172 |