Mercurial > hg > nginx
comparison src/http/modules/ngx_http_geo_module.c @ 4992:3be3de31d7dd
Geo: IPv6 support.
The "ranges" mode is still limited to IPv4 only.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Tue, 25 Dec 2012 08:21:56 +0000 |
parents | eababa1dc446 |
children | a8cc59ead621 |
comparison
equal
deleted
inserted
replaced
4991:a384c60d55f3 | 4992:3be3de31d7dd |
---|---|
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 |
255 if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) { | |
256 | |
257 switch (addr.sockaddr->sa_family) { | |
258 | |
259 #if (NGX_HAVE_INET6) | |
260 case AF_INET6: | |
261 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; | |
262 | |
263 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { | |
264 p = inaddr6->s6_addr; | |
265 | |
266 inaddr = p[12] << 24; | |
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 | |
192 if (ctx->u.high.low) { | 288 if (ctx->u.high.low) { |
193 addr = ngx_http_geo_addr(r, ctx); | 289 range = ctx->u.high.low[inaddr >> 16]; |
194 | |
195 range = ctx->u.high.low[addr >> 16]; | |
196 | 290 |
197 if (range) { | 291 if (range) { |
198 n = addr & 0xffff; | 292 n = inaddr & 0xffff; |
199 do { | 293 do { |
200 if (n >= (ngx_uint_t) range->start | 294 if (n >= (ngx_uint_t) range->start |
201 && n <= (ngx_uint_t) range->end) | 295 && n <= (ngx_uint_t) range->end) |
202 { | 296 { |
203 *v = *range->value; | 297 *v = *range->value; |
212 | 306 |
213 return NGX_OK; | 307 return NGX_OK; |
214 } | 308 } |
215 | 309 |
216 | 310 |
217 static in_addr_t | 311 static ngx_int_t |
218 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) | |
219 { | 314 { |
220 ngx_addr_t addr; | 315 ngx_table_elt_t *xfwd; |
221 ngx_table_elt_t *xfwd; | 316 |
222 struct sockaddr_in *sin; | 317 if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) { |
223 | 318 return NGX_ERROR; |
224 if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) { | |
225 return INADDR_NONE; | |
226 } | 319 } |
227 | 320 |
228 xfwd = r->headers_in.x_forwarded_for; | 321 xfwd = r->headers_in.x_forwarded_for; |
229 | 322 |
230 if (xfwd != NULL && ctx->proxies != NULL) { | 323 if (xfwd != NULL && ctx->proxies != NULL) { |
231 (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data, | 324 (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data, |
232 xfwd->value.len, ctx->proxies, | 325 xfwd->value.len, ctx->proxies, |
233 ctx->proxy_recursive); | 326 ctx->proxy_recursive); |
234 } | 327 } |
235 | 328 |
236 #if (NGX_HAVE_INET6) | 329 return NGX_OK; |
237 | |
238 if (addr.sockaddr->sa_family == AF_INET6) { | |
239 u_char *p; | |
240 in_addr_t inaddr; | |
241 struct in6_addr *inaddr6; | |
242 | |
243 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; | |
244 | |
245 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { | |
246 p = inaddr6->s6_addr; | |
247 | |
248 inaddr = p[12] << 24; | |
249 inaddr += p[13] << 16; | |
250 inaddr += p[14] << 8; | |
251 inaddr += p[15]; | |
252 | |
253 return inaddr; | |
254 } | |
255 } | |
256 | |
257 #endif | |
258 | |
259 if (addr.sockaddr->sa_family != AF_INET) { | |
260 return INADDR_NONE; | |
261 } | |
262 | |
263 sin = (struct sockaddr_in *) addr.sockaddr; | |
264 return ntohl(sin->sin_addr.s_addr); | |
265 } | 330 } |
266 | 331 |
267 | 332 |
268 static ngx_int_t | 333 static ngx_int_t |
269 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, |
313 ngx_pool_t *pool; | 378 ngx_pool_t *pool; |
314 ngx_array_t *a; | 379 ngx_array_t *a; |
315 ngx_http_variable_t *var; | 380 ngx_http_variable_t *var; |
316 ngx_http_geo_ctx_t *geo; | 381 ngx_http_geo_ctx_t *geo; |
317 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 | |
318 | 386 |
319 value = cf->args->elts; | 387 value = cf->args->elts; |
320 | 388 |
321 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t)); | 389 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t)); |
322 if (geo == NULL) { | 390 if (geo == NULL) { |
443 if (ctx.tree == NULL) { | 511 if (ctx.tree == NULL) { |
444 return NGX_CONF_ERROR; | 512 return NGX_CONF_ERROR; |
445 } | 513 } |
446 } | 514 } |
447 | 515 |
448 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 | |
449 | 528 |
450 var->get_handler = ngx_http_geo_cidr_variable; | 529 var->get_handler = ngx_http_geo_cidr_variable; |
451 var->data = (uintptr_t) geo; | 530 var->data = (uintptr_t) geo; |
452 | 531 |
453 ngx_destroy_pool(ctx.temp_pool); | 532 ngx_destroy_pool(ctx.temp_pool); |
459 { | 538 { |
460 return NGX_CONF_ERROR; | 539 return NGX_CONF_ERROR; |
461 } | 540 } |
462 | 541 |
463 /* NGX_BUSY is okay (default was set explicitly) */ | 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 | |
464 } | 552 } |
465 | 553 |
466 return rv; | 554 return rv; |
467 } | 555 } |
468 | 556 |
481 | 569 |
482 if (cf->args->nelts == 1) { | 570 if (cf->args->nelts == 1) { |
483 | 571 |
484 if (ngx_strcmp(value[0].data, "ranges") == 0) { | 572 if (ngx_strcmp(value[0].data, "ranges") == 0) { |
485 | 573 |
486 if (ctx->tree) { | 574 if (ctx->tree |
575 #if (NGX_HAVE_INET6) | |
576 || ctx->tree6 | |
577 #endif | |
578 ) | |
579 { | |
487 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 580 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
488 "the \"ranges\" directive must be " | 581 "the \"ranges\" directive must be " |
489 "the first directive inside \"geo\" block"); | 582 "the first directive inside \"geo\" block"); |
490 goto failed; | 583 goto failed; |
491 } | 584 } |
932 if (ctx->tree == NULL) { | 1025 if (ctx->tree == NULL) { |
933 return NGX_CONF_ERROR; | 1026 return NGX_CONF_ERROR; |
934 } | 1027 } |
935 } | 1028 } |
936 | 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 | |
937 if (ngx_strcmp(value[0].data, "default") == 0) { | 1039 if (ngx_strcmp(value[0].data, "default") == 0) { |
938 /* cidr.family = AF_INET; */ | 1040 /* cidr.family = AF_INET; */ |
939 cidr.u.in.addr = 0; | 1041 cidr.u.in.addr = 0; |
940 cidr.u.in.mask = 0; | 1042 cidr.u.in.mask = 0; |
941 net = &value[0]; | 1043 net = &value[0]; |
952 | 1054 |
953 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) { | 1055 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) { |
954 return NGX_CONF_ERROR; | 1056 return NGX_CONF_ERROR; |
955 } | 1057 } |
956 | 1058 |
957 if (cidr.family != AF_INET) { | 1059 if (cidr.family == AF_INET) { |
958 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1060 cidr.u.in.addr = ntohl(cidr.u.in.addr); |
959 "\"geo\" supports IPv4 only"); | 1061 cidr.u.in.mask = ntohl(cidr.u.in.mask); |
960 return NGX_CONF_ERROR; | 1062 } |
961 } | |
962 | |
963 cidr.u.in.addr = ntohl(cidr.u.in.addr); | |
964 cidr.u.in.mask = ntohl(cidr.u.in.mask); | |
965 | 1063 |
966 if (del) { | 1064 if (del) { |
967 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, | 1065 switch (cidr.family) { |
968 cidr.u.in.mask) | 1066 |
969 != NGX_OK) | 1067 #if (NGX_HAVE_INET6) |
970 { | 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) { | |
971 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | 1082 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
972 "no network \"%V\" to delete", net); | 1083 "no network \"%V\" to delete", net); |
973 } | 1084 } |
974 | 1085 |
975 return NGX_CONF_OK; | 1086 return NGX_CONF_OK; |
980 | 1091 |
981 if (val == NULL) { | 1092 if (val == NULL) { |
982 return NGX_CONF_ERROR; | 1093 return NGX_CONF_ERROR; |
983 } | 1094 } |
984 | 1095 |
985 for (i = 2; i; i--) { | 1096 switch (cidr.family) { |
986 rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask, | 1097 |
987 (uintptr_t) val); | 1098 #if (NGX_HAVE_INET6) |
988 if (rc == NGX_OK) { | 1099 case AF_INET6: |
989 return NGX_CONF_OK; | 1100 for (i = 2; i; i--) { |
990 } | 1101 rc = ngx_radix128tree_insert(ctx->tree6, cidr.u.in6.addr.s6_addr, |
991 | 1102 cidr.u.in6.mask.s6_addr, |
992 if (rc == NGX_ERROR) { | 1103 (uintptr_t) val); |
993 return NGX_CONF_ERROR; | 1104 |
994 } | 1105 if (rc == NGX_OK) { |
995 | 1106 return NGX_CONF_OK; |
996 /* rc == NGX_BUSY */ | 1107 } |
997 | 1108 |
998 old = (ngx_http_variable_value_t *) | 1109 if (rc == NGX_ERROR) { |
999 ngx_radix32tree_find(ctx->tree, cidr.u.in.addr); | 1110 return NGX_CONF_ERROR; |
1000 | 1111 } |
1001 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | 1112 |
1002 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", | 1113 /* rc == NGX_BUSY */ |
1003 net, val, old); | 1114 |
1004 | 1115 old = (ngx_http_variable_value_t *) |
1005 rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask); | 1116 ngx_radix128tree_find(ctx->tree6, |
1006 | 1117 cidr.u.in6.addr.s6_addr); |
1007 if (rc == NGX_ERROR) { | 1118 |
1008 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); | 1119 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
1009 return NGX_CONF_ERROR; | 1120 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", |
1010 } | 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; | |
1011 } | 1168 } |
1012 | 1169 |
1013 return NGX_CONF_ERROR; | 1170 return NGX_CONF_ERROR; |
1014 } | 1171 } |
1015 | 1172 |