nginxtra 1.2.6.8 → 1.2.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/bin/nginxtra +1 -1
  2. data/bin/nginxtra_rails +1 -1
  3. data/lib/nginxtra/version.rb +1 -1
  4. data/vendor/nginx/CHANGES +72 -0
  5. data/vendor/nginx/CHANGES.ru +76 -0
  6. data/vendor/nginx/LICENSE +2 -2
  7. data/vendor/nginx/auto/cc/msvc +0 -3
  8. data/vendor/nginx/auto/lib/geoip/conf +17 -2
  9. data/vendor/nginx/auto/lib/libgd/conf +1 -1
  10. data/vendor/nginx/auto/lib/pcre/conf +1 -0
  11. data/vendor/nginx/auto/lib/perl/make +1 -3
  12. data/vendor/nginx/auto/lib/zlib/conf +4 -1
  13. data/vendor/nginx/man/nginx.8 +2 -2
  14. data/vendor/nginx/src/core/nginx.h +2 -2
  15. data/vendor/nginx/src/core/ngx_conf_file.c +4 -19
  16. data/vendor/nginx/src/core/ngx_conf_file.h +1 -10
  17. data/vendor/nginx/src/core/ngx_cycle.c +2 -19
  18. data/vendor/nginx/src/core/ngx_file.c +4 -4
  19. data/vendor/nginx/src/core/ngx_inet.c +1 -1
  20. data/vendor/nginx/src/core/ngx_inet.h +1 -1
  21. data/vendor/nginx/src/core/ngx_radix_tree.c +202 -5
  22. data/vendor/nginx/src/core/ngx_radix_tree.h +9 -0
  23. data/vendor/nginx/src/event/modules/ngx_poll_module.c +2 -2
  24. data/vendor/nginx/src/event/ngx_event.c +4 -0
  25. data/vendor/nginx/src/event/ngx_event_openssl.c +27 -13
  26. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +38 -49
  27. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +44 -59
  28. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +310 -103
  29. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +145 -15
  30. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -1
  31. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +1 -0
  32. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +27 -13
  33. data/vendor/nginx/src/http/modules/ngx_http_log_module.c +378 -40
  34. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +7 -0
  35. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +9 -7
  36. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +1 -1
  37. data/vendor/nginx/src/http/modules/ngx_http_secure_link_module.c +15 -2
  38. data/vendor/nginx/src/http/modules/ngx_http_split_clients_module.c +1 -1
  39. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +2 -2
  40. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +4 -0
  41. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +3 -1
  42. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +1 -1
  43. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +2 -2
  44. data/vendor/nginx/src/http/modules/perl/Makefile.PL +3 -14
  45. data/vendor/nginx/src/http/modules/perl/nginx.pm +2 -2
  46. data/vendor/nginx/src/http/ngx_http_core_module.c +2 -1
  47. data/vendor/nginx/src/http/ngx_http_script.c +3 -7
  48. data/vendor/nginx/src/http/ngx_http_upstream.c +9 -0
  49. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +3 -1
  50. data/vendor/nginx/src/http/ngx_http_variables.c +114 -0
  51. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +1 -1
  52. data/vendor/nginx/src/os/unix/ngx_files.c +1 -1
  53. data/vendor/nginx/src/os/unix/ngx_user.c +13 -14
  54. metadata +2 -2
@@ -1356,11 +1356,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
1356
1356
  }
1357
1357
 
1358
1358
  } else {
1359
- if (f->padding) {
1360
- f->state = ngx_http_fastcgi_st_padding;
1361
- } else {
1362
- f->state = ngx_http_fastcgi_st_version;
1363
- }
1359
+ f->state = ngx_http_fastcgi_st_padding;
1364
1360
  }
1365
1361
 
1366
1362
  continue;
@@ -1597,11 +1593,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
1597
1593
  f->length -= u->buffer.pos - start;
1598
1594
 
1599
1595
  if (f->length == 0) {
1600
- if (f->padding) {
1601
- f->state = ngx_http_fastcgi_st_padding;
1602
- } else {
1603
- f->state = ngx_http_fastcgi_st_version;
1604
- }
1596
+ f->state = ngx_http_fastcgi_st_padding;
1605
1597
  }
1606
1598
 
1607
1599
  if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
@@ -1696,12 +1688,7 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1696
1688
  }
1697
1689
 
1698
1690
  if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1699
-
1700
- if (f->padding) {
1701
- f->state = ngx_http_fastcgi_st_padding;
1702
- } else {
1703
- f->state = ngx_http_fastcgi_st_version;
1704
- }
1691
+ f->state = ngx_http_fastcgi_st_padding;
1705
1692
 
1706
1693
  if (!flcf->keep_conn) {
1707
1694
  p->upstream_done = 1;
@@ -1715,27 +1702,38 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1715
1702
 
1716
1703
  if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1717
1704
 
1718
- if (f->padding) {
1719
- f->state = ngx_http_fastcgi_st_padding;
1720
- } else {
1721
- f->state = ngx_http_fastcgi_st_version;
1705
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1706
+ "http fastcgi sent end request");
1707
+
1708
+ if (!flcf->keep_conn) {
1709
+ p->upstream_done = 1;
1710
+ break;
1722
1711
  }
1723
1712
 
1724
- p->upstream_done = 1;
1713
+ continue;
1714
+ }
1715
+ }
1716
+
1717
+
1718
+ if (f->state == ngx_http_fastcgi_st_padding) {
1719
+
1720
+ if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1725
1721
 
1726
- if (flcf->keep_conn) {
1722
+ if (f->pos + f->padding < f->last) {
1723
+ p->upstream_done = 1;
1724
+ break;
1725
+ }
1726
+
1727
+ if (f->pos + f->padding == f->last) {
1728
+ p->upstream_done = 1;
1727
1729
  r->upstream->keepalive = 1;
1730
+ break;
1728
1731
  }
1729
1732
 
1730
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1731
- "http fastcgi sent end request");
1733
+ f->padding -= f->last - f->pos;
1732
1734
 
1733
1735
  break;
1734
1736
  }
1735
- }
1736
-
1737
-
1738
- if (f->state == ngx_http_fastcgi_st_padding) {
1739
1737
 
1740
1738
  if (f->pos + f->padding < f->last) {
1741
1739
  f->state = ngx_http_fastcgi_st_version;
@@ -1788,21 +1786,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1788
1786
  "FastCGI sent in stderr: \"%*s\"",
1789
1787
  m + 1 - msg, msg);
1790
1788
 
1791
- if (f->pos == f->last) {
1792
- break;
1793
- }
1794
-
1795
1789
  } else {
1796
- if (f->padding) {
1797
- f->state = ngx_http_fastcgi_st_padding;
1798
- } else {
1799
- f->state = ngx_http_fastcgi_st_version;
1800
- }
1790
+ f->state = ngx_http_fastcgi_st_padding;
1801
1791
  }
1802
1792
 
1803
1793
  continue;
1804
1794
  }
1805
1795
 
1796
+ if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1797
+
1798
+ if (f->pos + f->length <= f->last) {
1799
+ f->state = ngx_http_fastcgi_st_padding;
1800
+ f->pos += f->length;
1801
+
1802
+ continue;
1803
+ }
1804
+
1805
+ f->length -= f->last - f->pos;
1806
+
1807
+ break;
1808
+ }
1809
+
1806
1810
 
1807
1811
  /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1808
1812
 
@@ -1856,33 +1860,14 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1856
1860
  ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1857
1861
  "input buf #%d %p", b->num, b->pos);
1858
1862
 
1859
- if (f->pos + f->length < f->last) {
1860
-
1861
- if (f->padding) {
1862
- f->state = ngx_http_fastcgi_st_padding;
1863
- } else {
1864
- f->state = ngx_http_fastcgi_st_version;
1865
- }
1866
-
1863
+ if (f->pos + f->length <= f->last) {
1864
+ f->state = ngx_http_fastcgi_st_padding;
1867
1865
  f->pos += f->length;
1868
1866
  b->last = f->pos;
1869
1867
 
1870
1868
  continue;
1871
1869
  }
1872
1870
 
1873
- if (f->pos + f->length == f->last) {
1874
-
1875
- if (f->padding) {
1876
- f->state = ngx_http_fastcgi_st_padding;
1877
- } else {
1878
- f->state = ngx_http_fastcgi_st_version;
1879
- }
1880
-
1881
- b->last = f->last;
1882
-
1883
- break;
1884
- }
1885
-
1886
1871
  f->length -= f->last - f->pos;
1887
1872
 
1888
1873
  b->last = f->last;
@@ -3014,7 +2999,7 @@ ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3014
2999
 
3015
3000
  value = cf->args->elts;
3016
3001
 
3017
- if (flcf->cache_key.value.len) {
3002
+ if (flcf->cache_key.value.data) {
3018
3003
  return "is duplicate";
3019
3004
  }
3020
3005
 
@@ -17,6 +17,14 @@ typedef struct {
17
17
  } ngx_http_geo_range_t;
18
18
 
19
19
 
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
+
20
28
  typedef struct {
21
29
  ngx_http_geo_range_t **low;
22
30
  ngx_http_variable_value_t *default_value;
@@ -35,6 +43,9 @@ typedef struct {
35
43
  ngx_str_t *net;
36
44
  ngx_http_geo_high_ranges_t high;
37
45
  ngx_radix_tree_t *tree;
46
+ #if (NGX_HAVE_INET6)
47
+ ngx_radix_tree_t *tree6;
48
+ #endif
38
49
  ngx_rbtree_t rbtree;
39
50
  ngx_rbtree_node_t sentinel;
40
51
  ngx_array_t *proxies;
@@ -57,7 +68,7 @@ typedef struct {
57
68
 
58
69
  typedef struct {
59
70
  union {
60
- ngx_radix_tree_t *tree;
71
+ ngx_http_geo_trees_t trees;
61
72
  ngx_http_geo_high_ranges_t high;
62
73
  } u;
63
74
 
@@ -68,8 +79,8 @@ typedef struct {
68
79
  } ngx_http_geo_ctx_t;
69
80
 
70
81
 
71
- static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
72
- ngx_http_geo_ctx_t *ctx);
82
+ static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r,
83
+ ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
73
84
  static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
74
85
  ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
75
86
  static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@@ -82,6 +93,8 @@ static ngx_uint_t ngx_http_geo_delete_range(ngx_conf_t *cf,
82
93
  ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
83
94
  static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
84
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
98
  static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
86
99
  ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value);
87
100
  static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
@@ -155,7 +168,7 @@ static ngx_http_geo_header_t ngx_http_geo_header = {
155
168
  };
156
169
 
157
170
 
158
- /* AF_INET only */
171
+ /* geo range is AF_INET only */
159
172
 
160
173
  static ngx_int_t
161
174
  ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
@@ -163,10 +176,56 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
163
176
  {
164
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
182
  ngx_http_variable_value_t *vv;
183
+ #if (NGX_HAVE_INET6)
184
+ u_char *p;
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) {
167
195
 
168
- vv = (ngx_http_variable_value_t *)
169
- ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
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
230
  *v = *vv;
172
231
 
@@ -183,25 +242,65 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
183
242
  {
184
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
247
  ngx_uint_t n;
248
+ struct sockaddr_in *sin;
188
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
255
  *v = *ctx->u.high.default_value;
191
256
 
192
- addr = ngx_http_geo_addr(r, ctx);
257
+ if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
193
258
 
194
- range = ctx->u.high.low[addr >> 16];
259
+ switch (addr.sockaddr->sa_family) {
195
260
 
196
- if (range) {
197
- n = addr & 0xffff;
198
- do {
199
- if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
200
- {
201
- *v = *range->value;
202
- break;
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;
203
275
  }
204
- } while ((++range)->value);
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
+
290
+ if (ctx->u.high.low) {
291
+ range = ctx->u.high.low[inaddr >> 16];
292
+
293
+ if (range) {
294
+ n = inaddr & 0xffff;
295
+ do {
296
+ if (n >= (ngx_uint_t) range->start
297
+ && n <= (ngx_uint_t) range->end)
298
+ {
299
+ *v = *range->value;
300
+ break;
301
+ }
302
+ } while ((++range)->value);
303
+ }
205
304
  }
206
305
 
207
306
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -211,54 +310,25 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
211
310
  }
212
311
 
213
312
 
214
- static in_addr_t
215
- ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
313
+ static ngx_int_t
314
+ ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
315
+ ngx_addr_t *addr)
216
316
  {
217
- ngx_addr_t addr;
218
- ngx_table_elt_t *xfwd;
219
- struct sockaddr_in *sin;
317
+ ngx_table_elt_t *xfwd;
220
318
 
221
- if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) {
222
- return INADDR_NONE;
319
+ if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
320
+ return NGX_ERROR;
223
321
  }
224
322
 
225
323
  xfwd = r->headers_in.x_forwarded_for;
226
324
 
227
325
  if (xfwd != NULL && ctx->proxies != NULL) {
228
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
326
+ (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
229
327
  xfwd->value.len, ctx->proxies,
230
328
  ctx->proxy_recursive);
231
329
  }
232
330
 
233
- #if (NGX_HAVE_INET6)
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);
331
+ return NGX_OK;
262
332
  }
263
333
 
264
334
 
@@ -303,7 +373,6 @@ static char *
303
373
  ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
304
374
  {
305
375
  char *rv;
306
- void **p;
307
376
  size_t len;
308
377
  ngx_str_t *value, name;
309
378
  ngx_uint_t i;
@@ -313,6 +382,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
313
382
  ngx_http_variable_t *var;
314
383
  ngx_http_geo_ctx_t *geo;
315
384
  ngx_http_geo_conf_ctx_t ctx;
385
+ #if (NGX_HAVE_INET6)
386
+ static struct in6_addr zero;
387
+ #endif
316
388
 
317
389
  value = cf->args->elts;
318
390
 
@@ -322,6 +394,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
322
394
  }
323
395
 
324
396
  name = value[1];
397
+
398
+ if (name.data[0] != '$') {
399
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
400
+ "invalid variable name \"%V\"", &name);
401
+ return NGX_CONF_ERROR;
402
+ }
403
+
325
404
  name.len--;
326
405
  name.data++;
327
406
 
@@ -333,6 +412,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
333
412
  }
334
413
 
335
414
  name = value[2];
415
+
416
+ if (name.data[0] != '$') {
417
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
418
+ "invalid variable name \"%V\"", &name);
419
+ return NGX_CONF_ERROR;
420
+ }
421
+
336
422
  name.len--;
337
423
  name.data++;
338
424
 
@@ -378,9 +464,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
378
464
  geo->proxies = ctx.proxies;
379
465
  geo->proxy_recursive = ctx.proxy_recursive;
380
466
 
381
- if (ctx.high.low) {
467
+ if (ctx.ranges) {
382
468
 
383
- if (!ctx.binary_include) {
469
+ if (ctx.high.low && !ctx.binary_include) {
384
470
  for (i = 0; i < 0x10000; i++) {
385
471
  a = (ngx_array_t *) ctx.high.low[i];
386
472
 
@@ -395,8 +481,8 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
395
481
  return NGX_CONF_ERROR;
396
482
  }
397
483
 
398
- p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len);
399
- *p = NULL;
484
+ ngx_memcpy(ctx.high.low[i], a->elts, len);
485
+ ctx.high.low[i][a->nelts].value = NULL;
400
486
  ctx.data_size += len + sizeof(void *);
401
487
  }
402
488
 
@@ -429,7 +515,18 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
429
515
  }
430
516
  }
431
517
 
432
- 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
433
530
 
434
531
  var->get_handler = ngx_http_geo_cidr_variable;
435
532
  var->data = (uintptr_t) geo;
@@ -437,16 +534,23 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
437
534
  ngx_destroy_pool(ctx.temp_pool);
438
535
  ngx_destroy_pool(pool);
439
536
 
440
- if (ngx_radix32tree_find(ctx.tree, 0) != NGX_RADIX_NO_VALUE) {
441
- return rv;
442
- }
443
-
444
537
  if (ngx_radix32tree_insert(ctx.tree, 0, 0,
445
538
  (uintptr_t) &ngx_http_variable_null_value)
446
539
  == NGX_ERROR)
447
540
  {
448
541
  return NGX_CONF_ERROR;
449
542
  }
543
+
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
450
554
  }
451
555
 
452
556
  return rv;
@@ -469,7 +573,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
469
573
 
470
574
  if (ngx_strcmp(value[0].data, "ranges") == 0) {
471
575
 
472
- if (ctx->tree) {
576
+ if (ctx->tree
577
+ #if (NGX_HAVE_INET6)
578
+ || ctx->tree6
579
+ #endif
580
+ )
581
+ {
473
582
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
474
583
  "the \"ranges\" directive must be "
475
584
  "the first directive inside \"geo\" block");
@@ -907,11 +1016,10 @@ static char *
907
1016
  ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
908
1017
  ngx_str_t *value)
909
1018
  {
910
- ngx_int_t rc, del;
911
- ngx_str_t *net;
912
- ngx_uint_t i;
913
- ngx_cidr_t cidr;
914
- ngx_http_variable_value_t *val, *old;
1019
+ char *rv;
1020
+ ngx_int_t rc, del;
1021
+ ngx_str_t *net;
1022
+ ngx_cidr_t cidr;
915
1023
 
916
1024
  if (ctx->tree == NULL) {
917
1025
  ctx->tree = ngx_radix_tree_create(ctx->pool, -1);
@@ -920,57 +1028,146 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
920
1028
  }
921
1029
  }
922
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
+
923
1040
  if (ngx_strcmp(value[0].data, "default") == 0) {
924
- /* cidr.family = AF_INET; */
1041
+ cidr.family = AF_INET;
925
1042
  cidr.u.in.addr = 0;
926
1043
  cidr.u.in.mask = 0;
927
- net = &value[0];
928
1044
 
929
- } else {
930
- if (ngx_strcmp(value[0].data, "delete") == 0) {
931
- net = &value[1];
932
- del = 1;
1045
+ rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
933
1046
 
934
- } else {
935
- net = &value[0];
936
- del = 0;
1047
+ if (rv != NGX_CONF_OK) {
1048
+ return rv;
937
1049
  }
938
1050
 
939
- if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
940
- return NGX_CONF_ERROR;
941
- }
1051
+ #if (NGX_HAVE_INET6)
1052
+ cidr.family = AF_INET6;
1053
+ ngx_memzero(&cidr.u.in6, sizeof(ngx_in6_cidr_t));
942
1054
 
943
- if (cidr.family != AF_INET) {
944
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
945
- "\"geo\" supports IPv4 only");
946
- return NGX_CONF_ERROR;
1055
+ rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
1056
+
1057
+ if (rv != NGX_CONF_OK) {
1058
+ return rv;
947
1059
  }
1060
+ #endif
948
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 {
1070
+ net = &value[0];
1071
+ del = 0;
1072
+ }
1073
+
1074
+ if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
1075
+ return NGX_CONF_ERROR;
1076
+ }
1077
+
1078
+ if (cidr.family == AF_INET) {
949
1079
  cidr.u.in.addr = ntohl(cidr.u.in.addr);
950
1080
  cidr.u.in.mask = ntohl(cidr.u.in.mask);
1081
+ }
951
1082
 
952
- if (del) {
953
- if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
954
- cidr.u.in.mask)
955
- != NGX_OK)
956
- {
957
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
958
- "no network \"%V\" to delete", net);
959
- }
1083
+ if (del) {
1084
+ switch (cidr.family) {
960
1085
 
961
- return NGX_CONF_OK;
1086
+ #if (NGX_HAVE_INET6)
1087
+ case AF_INET6:
1088
+ rc = ngx_radix128tree_delete(ctx->tree6,
1089
+ cidr.u.in6.addr.s6_addr,
1090
+ cidr.u.in6.mask.s6_addr);
1091
+ break;
1092
+ #endif
1093
+
1094
+ default: /* AF_INET */
1095
+ rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
1096
+ cidr.u.in.mask);
1097
+ break;
962
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;
963
1106
  }
964
1107
 
965
- val = ngx_http_geo_value(cf, ctx, &value[1]);
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);
966
1120
 
967
1121
  if (val == NULL) {
968
1122
  return NGX_CONF_ERROR;
969
1123
  }
970
1124
 
971
- for (i = 2; i; i--) {
972
- rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
973
- (uintptr_t) val);
1125
+ switch (cidr->family) {
1126
+
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
+
1133
+ if (rc == NGX_OK) {
1134
+ return NGX_CONF_OK;
1135
+ }
1136
+
1137
+ if (rc == NGX_ERROR) {
1138
+ return NGX_CONF_ERROR;
1139
+ }
1140
+
1141
+ /* rc == NGX_BUSY */
1142
+
1143
+ old = (ngx_http_variable_value_t *)
1144
+ ngx_radix128tree_find(ctx->tree6,
1145
+ cidr->u.in6.addr.s6_addr);
1146
+
1147
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1148
+ "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1149
+ net, val, old);
1150
+
1151
+ rc = ngx_radix128tree_delete(ctx->tree6,
1152
+ cidr->u.in6.addr.s6_addr,
1153
+ cidr->u.in6.mask.s6_addr);
1154
+
1155
+ if (rc == NGX_ERROR) {
1156
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
1157
+ return NGX_CONF_ERROR;
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
+
974
1171
  if (rc == NGX_OK) {
975
1172
  return NGX_CONF_OK;
976
1173
  }
@@ -982,18 +1179,28 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
982
1179
  /* rc == NGX_BUSY */
983
1180
 
984
1181
  old = (ngx_http_variable_value_t *)
985
- ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
1182
+ ngx_radix32tree_find(ctx->tree, cidr->u.in.addr);
986
1183
 
987
1184
  ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
988
- "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
989
- net, val, old);
1185
+ "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1186
+ net, val, old);
990
1187
 
991
- rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
1188
+ rc = ngx_radix32tree_delete(ctx->tree,
1189
+ cidr->u.in.addr, cidr->u.in.mask);
992
1190
 
993
1191
  if (rc == NGX_ERROR) {
994
1192
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
995
1193
  return NGX_CONF_ERROR;
996
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;
997
1204
  }
998
1205
 
999
1206
  return NGX_CONF_ERROR;