comparison src/http/modules/ngx_http_geo_module.c @ 5048:2f0862333985 stable-1.2

Merge of r4993, r4994, r4997, r5000: geo ipv6 support. *) Geo: IPv6 support. The "ranges" mode is still limited to IPv4 only. *) Geo: properly initialize ngx_cidr_t when dealing with "default". *) Geo: made "default" affect both IPv4 and IPv6 when using prefixes. Previously, "default" was equivalent to specifying 0.0.0.0/0, now it's equivalent to specifying both 0.0.0.0/0 and ::/0 (if support for IPv6 is enabled) with the same value. *) Geo: improved code readability.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 11 Feb 2013 12:31:43 +0000
parents 852f40088278
children
comparison
equal deleted inserted replaced
5047:852f40088278 5048:2f0862333985
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,
80 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); 91 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
81 static ngx_uint_t ngx_http_geo_delete_range(ngx_conf_t *cf, 92 static ngx_uint_t ngx_http_geo_delete_range(ngx_conf_t *cf,
82 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); 93 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
83 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, 94 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
84 ngx_str_t *value); 95 ngx_str_t *value);
96 static char *ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
97 ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net);
85 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf, 98 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
86 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value); 99 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value);
87 static char *ngx_http_geo_add_proxy(ngx_conf_t *cf, 100 static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
88 ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr); 101 ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr);
89 static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, 102 static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
153 static ngx_http_geo_header_t ngx_http_geo_header = { 166 static ngx_http_geo_header_t ngx_http_geo_header = {
154 { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0 167 { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0
155 }; 168 };
156 169
157 170
158 /* AF_INET only */ 171 /* geo range is AF_INET only */
159 172
160 static ngx_int_t 173 static ngx_int_t
161 ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, 174 ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
162 uintptr_t data) 175 uintptr_t data)
163 { 176 {
164 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; 177 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
165 178
179 in_addr_t inaddr;
180 ngx_addr_t addr;
181 struct sockaddr_in *sin;
166 ngx_http_variable_value_t *vv; 182 ngx_http_variable_value_t *vv;
167 183 #if (NGX_HAVE_INET6)
168 vv = (ngx_http_variable_value_t *) 184 u_char *p;
169 ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx)); 185 struct in6_addr *inaddr6;
186 #endif
187
188 if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) {
189 vv = (ngx_http_variable_value_t *)
190 ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
191 goto done;
192 }
193
194 switch (addr.sockaddr->sa_family) {
195
196 #if (NGX_HAVE_INET6)
197 case AF_INET6:
198 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
199 p = inaddr6->s6_addr;
200
201 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
202 inaddr = p[12] << 24;
203 inaddr += p[13] << 16;
204 inaddr += p[14] << 8;
205 inaddr += p[15];
206
207 vv = (ngx_http_variable_value_t *)
208 ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
209
210 } else {
211 vv = (ngx_http_variable_value_t *)
212 ngx_radix128tree_find(ctx->u.trees.tree6, p);
213 }
214
215 break;
216 #endif
217
218 default: /* AF_INET */
219 sin = (struct sockaddr_in *) addr.sockaddr;
220 inaddr = ntohl(sin->sin_addr.s_addr);
221
222 vv = (ngx_http_variable_value_t *)
223 ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
224
225 break;
226 }
227
228 done:
170 229
171 *v = *vv; 230 *v = *vv;
172 231
173 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 232 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
174 "http geo: %v", v); 233 "http geo: %v", v);
181 ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, 240 ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
182 uintptr_t data) 241 uintptr_t data)
183 { 242 {
184 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; 243 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
185 244
186 in_addr_t addr; 245 in_addr_t inaddr;
246 ngx_addr_t addr;
187 ngx_uint_t n; 247 ngx_uint_t n;
248 struct sockaddr_in *sin;
188 ngx_http_geo_range_t *range; 249 ngx_http_geo_range_t *range;
250 #if (NGX_HAVE_INET6)
251 u_char *p;
252 struct in6_addr *inaddr6;
253 #endif
189 254
190 *v = *ctx->u.high.default_value; 255 *v = *ctx->u.high.default_value;
191 256
257 if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
258
259 switch (addr.sockaddr->sa_family) {
260
261 #if (NGX_HAVE_INET6)
262 case AF_INET6:
263 inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
264
265 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
266 p = inaddr6->s6_addr;
267
268 inaddr = p[12] << 24;
269 inaddr += p[13] << 16;
270 inaddr += p[14] << 8;
271 inaddr += p[15];
272
273 } else {
274 inaddr = INADDR_NONE;
275 }
276
277 break;
278 #endif
279
280 default: /* AF_INET */
281 sin = (struct sockaddr_in *) addr.sockaddr;
282 inaddr = ntohl(sin->sin_addr.s_addr);
283 break;
284 }
285
286 } else {
287 inaddr = INADDR_NONE;
288 }
289
192 if (ctx->u.high.low) { 290 if (ctx->u.high.low) {
193 addr = ngx_http_geo_addr(r, ctx); 291 range = ctx->u.high.low[inaddr >> 16];
194
195 range = ctx->u.high.low[addr >> 16];
196 292
197 if (range) { 293 if (range) {
198 n = addr & 0xffff; 294 n = inaddr & 0xffff;
199 do { 295 do {
200 if (n >= (ngx_uint_t) range->start 296 if (n >= (ngx_uint_t) range->start
201 && n <= (ngx_uint_t) range->end) 297 && n <= (ngx_uint_t) range->end)
202 { 298 {
203 *v = *range->value; 299 *v = *range->value;
212 308
213 return NGX_OK; 309 return NGX_OK;
214 } 310 }
215 311
216 312
217 static in_addr_t 313 static ngx_int_t
218 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) 314 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
219 { 315 ngx_addr_t *addr)
220 ngx_addr_t addr; 316 {
221 ngx_table_elt_t *xfwd; 317 ngx_table_elt_t *xfwd;
222 struct sockaddr_in *sin; 318
223 319 if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
224 if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) { 320 return NGX_ERROR;
225 return INADDR_NONE;
226 } 321 }
227 322
228 xfwd = r->headers_in.x_forwarded_for; 323 xfwd = r->headers_in.x_forwarded_for;
229 324
230 if (xfwd != NULL && ctx->proxies != NULL) { 325 if (xfwd != NULL && ctx->proxies != NULL) {
231 (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data, 326 (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
232 xfwd->value.len, ctx->proxies, 327 xfwd->value.len, ctx->proxies,
233 ctx->proxy_recursive); 328 ctx->proxy_recursive);
234 } 329 }
235 330
236 #if (NGX_HAVE_INET6) 331 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 } 332 }
266 333
267 334
268 static ngx_int_t 335 static ngx_int_t
269 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx, 336 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
313 ngx_pool_t *pool; 380 ngx_pool_t *pool;
314 ngx_array_t *a; 381 ngx_array_t *a;
315 ngx_http_variable_t *var; 382 ngx_http_variable_t *var;
316 ngx_http_geo_ctx_t *geo; 383 ngx_http_geo_ctx_t *geo;
317 ngx_http_geo_conf_ctx_t ctx; 384 ngx_http_geo_conf_ctx_t ctx;
385 #if (NGX_HAVE_INET6)
386 static struct in6_addr zero;
387 #endif
318 388
319 value = cf->args->elts; 389 value = cf->args->elts;
320 390
321 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t)); 391 geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t));
322 if (geo == NULL) { 392 if (geo == NULL) {
443 if (ctx.tree == NULL) { 513 if (ctx.tree == NULL) {
444 return NGX_CONF_ERROR; 514 return NGX_CONF_ERROR;
445 } 515 }
446 } 516 }
447 517
448 geo->u.tree = ctx.tree; 518 geo->u.trees.tree = ctx.tree;
519
520 #if (NGX_HAVE_INET6)
521 if (ctx.tree6 == NULL) {
522 ctx.tree6 = ngx_radix_tree_create(cf->pool, -1);
523 if (ctx.tree6 == NULL) {
524 return NGX_CONF_ERROR;
525 }
526 }
527
528 geo->u.trees.tree6 = ctx.tree6;
529 #endif
449 530
450 var->get_handler = ngx_http_geo_cidr_variable; 531 var->get_handler = ngx_http_geo_cidr_variable;
451 var->data = (uintptr_t) geo; 532 var->data = (uintptr_t) geo;
452 533
453 ngx_destroy_pool(ctx.temp_pool); 534 ngx_destroy_pool(ctx.temp_pool);
459 { 540 {
460 return NGX_CONF_ERROR; 541 return NGX_CONF_ERROR;
461 } 542 }
462 543
463 /* NGX_BUSY is okay (default was set explicitly) */ 544 /* NGX_BUSY is okay (default was set explicitly) */
545
546 #if (NGX_HAVE_INET6)
547 if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
548 (uintptr_t) &ngx_http_variable_null_value)
549 == NGX_ERROR)
550 {
551 return NGX_CONF_ERROR;
552 }
553 #endif
464 } 554 }
465 555
466 return rv; 556 return rv;
467 } 557 }
468 558
481 571
482 if (cf->args->nelts == 1) { 572 if (cf->args->nelts == 1) {
483 573
484 if (ngx_strcmp(value[0].data, "ranges") == 0) { 574 if (ngx_strcmp(value[0].data, "ranges") == 0) {
485 575
486 if (ctx->tree) { 576 if (ctx->tree
577 #if (NGX_HAVE_INET6)
578 || ctx->tree6
579 #endif
580 )
581 {
487 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 582 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
488 "the \"ranges\" directive must be " 583 "the \"ranges\" directive must be "
489 "the first directive inside \"geo\" block"); 584 "the first directive inside \"geo\" block");
490 goto failed; 585 goto failed;
491 } 586 }
919 1014
920 static char * 1015 static char *
921 ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, 1016 ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
922 ngx_str_t *value) 1017 ngx_str_t *value)
923 { 1018 {
924 ngx_int_t rc, del; 1019 char *rv;
925 ngx_str_t *net; 1020 ngx_int_t rc, del;
926 ngx_uint_t i; 1021 ngx_str_t *net;
927 ngx_cidr_t cidr; 1022 ngx_cidr_t cidr;
928 ngx_http_variable_value_t *val, *old;
929 1023
930 if (ctx->tree == NULL) { 1024 if (ctx->tree == NULL) {
931 ctx->tree = ngx_radix_tree_create(ctx->pool, -1); 1025 ctx->tree = ngx_radix_tree_create(ctx->pool, -1);
932 if (ctx->tree == NULL) { 1026 if (ctx->tree == NULL) {
933 return NGX_CONF_ERROR; 1027 return NGX_CONF_ERROR;
934 } 1028 }
935 } 1029 }
936 1030
1031 #if (NGX_HAVE_INET6)
1032 if (ctx->tree6 == NULL) {
1033 ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1);
1034 if (ctx->tree6 == NULL) {
1035 return NGX_CONF_ERROR;
1036 }
1037 }
1038 #endif
1039
937 if (ngx_strcmp(value[0].data, "default") == 0) { 1040 if (ngx_strcmp(value[0].data, "default") == 0) {
938 /* cidr.family = AF_INET; */ 1041 cidr.family = AF_INET;
939 cidr.u.in.addr = 0; 1042 cidr.u.in.addr = 0;
940 cidr.u.in.mask = 0; 1043 cidr.u.in.mask = 0;
1044
1045 rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
1046
1047 if (rv != NGX_CONF_OK) {
1048 return rv;
1049 }
1050
1051 #if (NGX_HAVE_INET6)
1052 cidr.family = AF_INET6;
1053 ngx_memzero(&cidr.u.in6, sizeof(ngx_in6_cidr_t));
1054
1055 rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
1056
1057 if (rv != NGX_CONF_OK) {
1058 return rv;
1059 }
1060 #endif
1061
1062 return NGX_CONF_OK;
1063 }
1064
1065 if (ngx_strcmp(value[0].data, "delete") == 0) {
1066 net = &value[1];
1067 del = 1;
1068
1069 } else {
941 net = &value[0]; 1070 net = &value[0];
942 1071 del = 0;
943 } else { 1072 }
944 if (ngx_strcmp(value[0].data, "delete") == 0) { 1073
945 net = &value[1]; 1074 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
946 del = 1; 1075 return NGX_CONF_ERROR;
947 1076 }
948 } else { 1077
949 net = &value[0]; 1078 if (cidr.family == AF_INET) {
950 del = 0;
951 }
952
953 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
954 return NGX_CONF_ERROR;
955 }
956
957 if (cidr.family != AF_INET) {
958 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
959 "\"geo\" supports IPv4 only");
960 return NGX_CONF_ERROR;
961 }
962
963 cidr.u.in.addr = ntohl(cidr.u.in.addr); 1079 cidr.u.in.addr = ntohl(cidr.u.in.addr);
964 cidr.u.in.mask = ntohl(cidr.u.in.mask); 1080 cidr.u.in.mask = ntohl(cidr.u.in.mask);
965 1081 }
966 if (del) { 1082
967 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, 1083 if (del) {
968 cidr.u.in.mask) 1084 switch (cidr.family) {
969 != NGX_OK) 1085
970 { 1086 #if (NGX_HAVE_INET6)
971 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, 1087 case AF_INET6:
972 "no network \"%V\" to delete", net); 1088 rc = ngx_radix128tree_delete(ctx->tree6,
973 } 1089 cidr.u.in6.addr.s6_addr,
974 1090 cidr.u.in6.mask.s6_addr);
975 return NGX_CONF_OK; 1091 break;
976 } 1092 #endif
977 } 1093
978 1094 default: /* AF_INET */
979 val = ngx_http_geo_value(cf, ctx, &value[1]); 1095 rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
1096 cidr.u.in.mask);
1097 break;
1098 }
1099
1100 if (rc != NGX_OK) {
1101 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1102 "no network \"%V\" to delete", net);
1103 }
1104
1105 return NGX_CONF_OK;
1106 }
1107
1108 return ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], net);
1109 }
1110
1111
1112 static char *
1113 ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
1114 ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net)
1115 {
1116 ngx_int_t rc;
1117 ngx_http_variable_value_t *val, *old;
1118
1119 val = ngx_http_geo_value(cf, ctx, value);
980 1120
981 if (val == NULL) { 1121 if (val == NULL) {
982 return NGX_CONF_ERROR; 1122 return NGX_CONF_ERROR;
983 } 1123 }
984 1124
985 for (i = 2; i; i--) { 1125 switch (cidr->family) {
986 rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask, 1126
987 (uintptr_t) val); 1127 #if (NGX_HAVE_INET6)
1128 case AF_INET6:
1129 rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
1130 cidr->u.in6.mask.s6_addr,
1131 (uintptr_t) val);
1132
988 if (rc == NGX_OK) { 1133 if (rc == NGX_OK) {
989 return NGX_CONF_OK; 1134 return NGX_CONF_OK;
990 } 1135 }
991 1136
992 if (rc == NGX_ERROR) { 1137 if (rc == NGX_ERROR) {
994 } 1139 }
995 1140
996 /* rc == NGX_BUSY */ 1141 /* rc == NGX_BUSY */
997 1142
998 old = (ngx_http_variable_value_t *) 1143 old = (ngx_http_variable_value_t *)
999 ngx_radix32tree_find(ctx->tree, cidr.u.in.addr); 1144 ngx_radix128tree_find(ctx->tree6,
1145 cidr->u.in6.addr.s6_addr);
1000 1146
1001 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, 1147 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1002 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", 1148 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1003 net, val, old); 1149 net, val, old);
1004 1150
1005 rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask); 1151 rc = ngx_radix128tree_delete(ctx->tree6,
1152 cidr->u.in6.addr.s6_addr,
1153 cidr->u.in6.mask.s6_addr);
1006 1154
1007 if (rc == NGX_ERROR) { 1155 if (rc == NGX_ERROR) {
1008 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); 1156 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
1009 return NGX_CONF_ERROR; 1157 return NGX_CONF_ERROR;
1010 } 1158 }
1159
1160 rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
1161 cidr->u.in6.mask.s6_addr,
1162 (uintptr_t) val);
1163
1164 break;
1165 #endif
1166
1167 default: /* AF_INET */
1168 rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
1169 cidr->u.in.mask, (uintptr_t) val);
1170
1171 if (rc == NGX_OK) {
1172 return NGX_CONF_OK;
1173 }
1174
1175 if (rc == NGX_ERROR) {
1176 return NGX_CONF_ERROR;
1177 }
1178
1179 /* rc == NGX_BUSY */
1180
1181 old = (ngx_http_variable_value_t *)
1182 ngx_radix32tree_find(ctx->tree, cidr->u.in.addr);
1183
1184 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1185 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1186 net, val, old);
1187
1188 rc = ngx_radix32tree_delete(ctx->tree,
1189 cidr->u.in.addr, cidr->u.in.mask);
1190
1191 if (rc == NGX_ERROR) {
1192 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
1193 return NGX_CONF_ERROR;
1194 }
1195
1196 rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
1197 cidr->u.in.mask, (uintptr_t) val);
1198
1199 break;
1200 }
1201
1202 if (rc == NGX_OK) {
1203 return NGX_CONF_OK;
1011 } 1204 }
1012 1205
1013 return NGX_CONF_ERROR; 1206 return NGX_CONF_ERROR;
1014 } 1207 }
1015 1208