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