nginxtra 1.4.7.9 → 1.6.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nginxtra +1 -1
  3. data/bin/nginxtra_rails +1 -1
  4. data/lib/nginxtra/version.rb +1 -1
  5. data/vendor/nginx/CHANGES +286 -19
  6. data/vendor/nginx/CHANGES.ru +296 -22
  7. data/vendor/nginx/auto/cc/clang +4 -3
  8. data/vendor/nginx/auto/cc/conf +23 -0
  9. data/vendor/nginx/auto/cc/msvc +1 -0
  10. data/vendor/nginx/auto/cc/name +1 -1
  11. data/vendor/nginx/auto/cc/owc +4 -4
  12. data/vendor/nginx/auto/cc/sunc +1 -1
  13. data/vendor/nginx/auto/endianness +2 -2
  14. data/vendor/nginx/auto/feature +1 -1
  15. data/vendor/nginx/auto/include +1 -1
  16. data/vendor/nginx/auto/lib/libatomic/make +3 -1
  17. data/vendor/nginx/auto/lib/openssl/conf +4 -0
  18. data/vendor/nginx/auto/lib/openssl/make +1 -1
  19. data/vendor/nginx/auto/lib/pcre/conf +5 -0
  20. data/vendor/nginx/auto/lib/pcre/make +11 -11
  21. data/vendor/nginx/auto/lib/pcre/makefile.bcc +4 -3
  22. data/vendor/nginx/auto/lib/pcre/makefile.msvc +2 -1
  23. data/vendor/nginx/auto/lib/pcre/makefile.owc +2 -1
  24. data/vendor/nginx/auto/lib/perl/make +1 -0
  25. data/vendor/nginx/auto/lib/test +1 -1
  26. data/vendor/nginx/auto/lib/zlib/make +22 -1
  27. data/vendor/nginx/auto/modules +8 -0
  28. data/vendor/nginx/auto/options +3 -0
  29. data/vendor/nginx/auto/os/darwin +1 -1
  30. data/vendor/nginx/auto/os/linux +32 -0
  31. data/vendor/nginx/auto/os/win32 +12 -1
  32. data/vendor/nginx/auto/sources +8 -2
  33. data/vendor/nginx/auto/types/sizeof +1 -1
  34. data/vendor/nginx/auto/types/typedef +1 -1
  35. data/vendor/nginx/auto/types/uintptr_t +1 -1
  36. data/vendor/nginx/auto/unix +13 -1
  37. data/vendor/nginx/conf/mime.types +11 -2
  38. data/vendor/nginx/conf/nginx.conf +3 -4
  39. data/vendor/nginx/contrib/README +6 -0
  40. data/vendor/nginx/contrib/vim/ftdetect/nginx.vim +4 -0
  41. data/vendor/nginx/contrib/vim/indent/nginx.vim +11 -0
  42. data/vendor/nginx/contrib/vim/syntax/nginx.vim +703 -0
  43. data/vendor/nginx/src/core/nginx.c +2 -7
  44. data/vendor/nginx/src/core/nginx.h +2 -2
  45. data/vendor/nginx/src/core/ngx_conf_file.c +8 -88
  46. data/vendor/nginx/src/core/ngx_conf_file.h +3 -3
  47. data/vendor/nginx/src/core/ngx_config.h +2 -2
  48. data/vendor/nginx/src/core/ngx_connection.c +100 -29
  49. data/vendor/nginx/src/core/ngx_connection.h +11 -0
  50. data/vendor/nginx/src/core/ngx_core.h +1 -0
  51. data/vendor/nginx/src/core/ngx_cycle.c +23 -99
  52. data/vendor/nginx/src/core/ngx_cycle.h +2 -0
  53. data/vendor/nginx/src/core/ngx_file.c +100 -8
  54. data/vendor/nginx/src/core/ngx_file.h +3 -0
  55. data/vendor/nginx/src/core/ngx_hash.c +6 -9
  56. data/vendor/nginx/src/core/ngx_inet.c +93 -5
  57. data/vendor/nginx/src/core/ngx_inet.h +4 -2
  58. data/vendor/nginx/src/core/ngx_list.c +1 -9
  59. data/vendor/nginx/src/core/ngx_log.c +132 -30
  60. data/vendor/nginx/src/core/ngx_log.h +5 -2
  61. data/vendor/nginx/src/core/ngx_open_file_cache.c +67 -1
  62. data/vendor/nginx/src/core/ngx_palloc.c +5 -2
  63. data/vendor/nginx/src/core/ngx_proxy_protocol.c +91 -0
  64. data/vendor/nginx/src/core/ngx_proxy_protocol.h +23 -0
  65. data/vendor/nginx/src/core/ngx_resolver.c +1080 -285
  66. data/vendor/nginx/src/core/ngx_resolver.h +33 -3
  67. data/vendor/nginx/src/core/ngx_slab.c +7 -2
  68. data/vendor/nginx/src/core/ngx_slab.h +2 -0
  69. data/vendor/nginx/src/core/ngx_string.c +78 -13
  70. data/vendor/nginx/src/core/ngx_string.h +2 -0
  71. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +2 -2
  72. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +13 -5
  73. data/vendor/nginx/src/event/modules/ngx_select_module.c +1 -1
  74. data/vendor/nginx/src/event/modules/ngx_win32_select_module.c +2 -2
  75. data/vendor/nginx/src/event/ngx_event.c +0 -1
  76. data/vendor/nginx/src/event/ngx_event.h +7 -6
  77. data/vendor/nginx/src/event/ngx_event_accept.c +6 -4
  78. data/vendor/nginx/src/event/ngx_event_connect.c +2 -2
  79. data/vendor/nginx/src/event/ngx_event_openssl.c +304 -13
  80. data/vendor/nginx/src/event/ngx_event_openssl.h +20 -1
  81. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +35 -23
  82. data/vendor/nginx/src/event/ngx_event_pipe.c +15 -30
  83. data/vendor/nginx/src/http/modules/ngx_http_access_module.c +115 -35
  84. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
  85. data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +444 -0
  86. data/vendor/nginx/src/http/modules/ngx_http_autoindex_module.c +2 -1
  87. data/vendor/nginx/src/http/modules/ngx_http_charset_filter_module.c +1 -1
  88. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +1 -3
  89. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +251 -36
  90. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +9 -5
  91. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -3
  92. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +1 -1
  93. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +4 -0
  94. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +8 -2
  95. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +5 -1
  96. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +3 -3
  97. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +21 -10
  98. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +669 -197
  99. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +93 -60
  100. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +13 -6
  101. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +20 -1
  102. data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +132 -74
  103. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +18 -12
  104. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +22 -20
  105. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +121 -3
  106. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +5 -0
  107. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +3 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +123 -91
  109. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +29 -19
  110. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +2 -5
  111. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +215 -19
  112. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +32 -6
  113. data/vendor/nginx/src/http/modules/perl/nginx.xs +4 -7
  114. data/vendor/nginx/src/http/modules/perl/ngx_http_perl_module.c +2 -2
  115. data/vendor/nginx/src/http/ngx_http.c +17 -7
  116. data/vendor/nginx/src/http/ngx_http_cache.h +4 -2
  117. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +4 -2
  118. data/vendor/nginx/src/http/ngx_http_core_module.c +63 -50
  119. data/vendor/nginx/src/http/ngx_http_core_module.h +5 -0
  120. data/vendor/nginx/src/http/ngx_http_file_cache.c +115 -3
  121. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -6
  122. data/vendor/nginx/src/http/ngx_http_parse.c +88 -10
  123. data/vendor/nginx/src/http/ngx_http_postpone_filter_module.c +2 -4
  124. data/vendor/nginx/src/http/ngx_http_request.c +116 -8
  125. data/vendor/nginx/src/http/ngx_http_request.h +5 -1
  126. data/vendor/nginx/src/http/ngx_http_request_body.c +7 -7
  127. data/vendor/nginx/src/http/ngx_http_script.c +6 -5
  128. data/vendor/nginx/src/http/ngx_http_spdy.c +889 -271
  129. data/vendor/nginx/src/http/ngx_http_spdy.h +51 -28
  130. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +382 -167
  131. data/vendor/nginx/src/http/ngx_http_spdy_module.c +65 -8
  132. data/vendor/nginx/src/http/ngx_http_spdy_module.h +5 -0
  133. data/vendor/nginx/src/http/ngx_http_special_response.c +1 -1
  134. data/vendor/nginx/src/http/ngx_http_upstream.c +290 -114
  135. data/vendor/nginx/src/http/ngx_http_upstream.h +9 -5
  136. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +32 -24
  137. data/vendor/nginx/src/http/ngx_http_variables.c +40 -6
  138. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +12 -5
  139. data/vendor/nginx/src/mail/ngx_mail.c +4 -2
  140. data/vendor/nginx/src/mail/ngx_mail.h +2 -0
  141. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +0 -1
  142. data/vendor/nginx/src/mail/ngx_mail_core_module.c +2 -1
  143. data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -4
  144. data/vendor/nginx/src/mail/ngx_mail_parse.c +32 -2
  145. data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +54 -7
  146. data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +50 -78
  147. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +48 -11
  148. data/vendor/nginx/src/mail/ngx_mail_ssl_module.h +3 -0
  149. data/vendor/nginx/src/os/unix/ngx_channel.c +3 -1
  150. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  151. data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -1
  152. data/vendor/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +14 -16
  153. data/vendor/nginx/src/os/unix/ngx_errno.h +3 -0
  154. data/vendor/nginx/src/os/unix/ngx_files.h +10 -16
  155. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +6 -0
  156. data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -1
  157. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +1 -1
  158. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.h +2 -2
  159. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +17 -19
  160. data/vendor/nginx/src/os/unix/ngx_linux_config.h +8 -2
  161. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +20 -22
  162. data/vendor/nginx/src/os/unix/ngx_posix_config.h +1 -0
  163. data/vendor/nginx/src/os/unix/ngx_process.c +5 -0
  164. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +15 -3
  165. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +2 -1
  166. data/vendor/nginx/src/os/unix/ngx_recv.c +4 -1
  167. data/vendor/nginx/src/os/unix/ngx_solaris_config.h +1 -0
  168. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +14 -16
  169. metadata +8 -2
@@ -105,11 +105,14 @@ ngx_reset_pool(ngx_pool_t *pool)
105
105
  }
106
106
  }
107
107
 
108
- pool->large = NULL;
109
-
110
108
  for (p = pool; p; p = p->d.next) {
111
109
  p->d.last = (u_char *) p + sizeof(ngx_pool_t);
110
+ p->d.failed = 0;
112
111
  }
112
+
113
+ pool->current = pool;
114
+ pool->chain = NULL;
115
+ pool->large = NULL;
113
116
  }
114
117
 
115
118
 
@@ -0,0 +1,91 @@
1
+
2
+ /*
3
+ * Copyright (C) Roman Arutyunyan
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #include <ngx_config.h>
9
+ #include <ngx_core.h>
10
+
11
+
12
+ u_char *
13
+ ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
14
+ {
15
+ size_t len;
16
+ u_char ch, *p, *addr;
17
+
18
+ p = buf;
19
+ len = last - buf;
20
+
21
+ if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
22
+ goto invalid;
23
+ }
24
+
25
+ p += 6;
26
+ len -= 6;
27
+
28
+ if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
29
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
30
+ "PROXY protocol unknown protocol");
31
+ p += 7;
32
+ goto skip;
33
+ }
34
+
35
+ if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
36
+ || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
37
+ {
38
+ goto invalid;
39
+ }
40
+
41
+ p += 5;
42
+ addr = p;
43
+
44
+ for ( ;; ) {
45
+ if (p == last) {
46
+ goto invalid;
47
+ }
48
+
49
+ ch = *p++;
50
+
51
+ if (ch == ' ') {
52
+ break;
53
+ }
54
+
55
+ if (ch != ':' && ch != '.'
56
+ && (ch < 'a' || ch > 'f')
57
+ && (ch < 'A' || ch > 'F')
58
+ && (ch < '0' || ch > '9'))
59
+ {
60
+ goto invalid;
61
+ }
62
+ }
63
+
64
+ len = p - addr - 1;
65
+ c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
66
+
67
+ if (c->proxy_protocol_addr.data == NULL) {
68
+ return NULL;
69
+ }
70
+
71
+ ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
72
+ c->proxy_protocol_addr.len = len;
73
+
74
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
75
+ "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
76
+
77
+ skip:
78
+
79
+ for ( /* void */ ; p < last - 1; p++) {
80
+ if (p[0] == CR && p[1] == LF) {
81
+ return p + 2;
82
+ }
83
+ }
84
+
85
+ invalid:
86
+
87
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
88
+ "broken header: \"%*s\"", (size_t) (last - buf), buf);
89
+
90
+ return NULL;
91
+ }
@@ -0,0 +1,23 @@
1
+
2
+ /*
3
+ * Copyright (C) Roman Arutyunyan
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
9
+ #define _NGX_PROXY_PROTOCOL_H_INCLUDED_
10
+
11
+
12
+ #include <ngx_config.h>
13
+ #include <ngx_core.h>
14
+
15
+
16
+ #define NGX_PROXY_PROTOCOL_MAX_HEADER 107
17
+
18
+
19
+ u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
20
+ u_char *last);
21
+
22
+
23
+ #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
@@ -26,7 +26,7 @@ typedef struct {
26
26
  u_char nns_lo;
27
27
  u_char nar_hi;
28
28
  u_char nar_lo;
29
- } ngx_resolver_query_t;
29
+ } ngx_resolver_hdr_t;
30
30
 
31
31
 
32
32
  typedef struct {
@@ -70,7 +70,8 @@ static void ngx_resolver_read_response(ngx_event_t *rev);
70
70
  static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
71
71
  size_t n);
72
72
  static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
73
- ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
73
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
74
+ ngx_uint_t nan, ngx_uint_t ans);
74
75
  static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
75
76
  ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
76
77
  static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
@@ -88,10 +89,17 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
88
89
  static void ngx_resolver_free(ngx_resolver_t *r, void *p);
89
90
  static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
90
91
  static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
91
- static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
92
- ngx_uint_t n);
92
+ static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
93
+ ngx_resolver_node_t *rn, ngx_uint_t rotate);
93
94
  static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
94
95
 
96
+ #if (NGX_HAVE_INET6)
97
+ static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
98
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
99
+ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
100
+ struct in6_addr *addr, uint32_t hash);
101
+ #endif
102
+
95
103
 
96
104
  ngx_resolver_t *
97
105
  ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
@@ -134,6 +142,17 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
134
142
  ngx_queue_init(&r->name_expire_queue);
135
143
  ngx_queue_init(&r->addr_expire_queue);
136
144
 
145
+ #if (NGX_HAVE_INET6)
146
+ r->ipv6 = 1;
147
+
148
+ ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
149
+ ngx_resolver_rbtree_insert_addr6_value);
150
+
151
+ ngx_queue_init(&r->addr6_resend_queue);
152
+
153
+ ngx_queue_init(&r->addr6_expire_queue);
154
+ #endif
155
+
137
156
  r->event->handler = ngx_resolver_resend_handler;
138
157
  r->event->data = r;
139
158
  r->event->log = &cf->cycle->new_log;
@@ -171,6 +190,25 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
171
190
  continue;
172
191
  }
173
192
 
193
+ #if (NGX_HAVE_INET6)
194
+ if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
195
+
196
+ if (ngx_strcmp(&names[i].data[5], "on") == 0) {
197
+ r->ipv6 = 1;
198
+
199
+ } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
200
+ r->ipv6 = 0;
201
+
202
+ } else {
203
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
204
+ "invalid parameter: %V", &names[i]);
205
+ return NULL;
206
+ }
207
+
208
+ continue;
209
+ }
210
+ #endif
211
+
174
212
  ngx_memzero(&u, sizeof(ngx_url_t));
175
213
 
176
214
  u.url = names[i];
@@ -220,6 +258,10 @@ ngx_resolver_cleanup(void *data)
220
258
 
221
259
  ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
222
260
 
261
+ #if (NGX_HAVE_INET6)
262
+ ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
263
+ #endif
264
+
223
265
  if (r->event) {
224
266
  ngx_free(r->event);
225
267
  }
@@ -281,7 +323,11 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
281
323
  temp->state = NGX_OK;
282
324
  temp->naddrs = 1;
283
325
  temp->addrs = &temp->addr;
284
- temp->addr = addr;
326
+ temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
327
+ temp->addr.socklen = sizeof(struct sockaddr_in);
328
+ ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
329
+ temp->sin.sin_family = AF_INET;
330
+ temp->sin.sin_addr.s_addr = addr;
285
331
  temp->quick = 1;
286
332
 
287
333
  return temp;
@@ -310,6 +356,10 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx)
310
356
 
311
357
  r = ctx->resolver;
312
358
 
359
+ if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
360
+ ctx->name.len--;
361
+ }
362
+
313
363
  ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
314
364
  "resolve: \"%V\"", &ctx->name);
315
365
 
@@ -411,18 +461,18 @@ done:
411
461
  }
412
462
 
413
463
 
414
- /* NGX_RESOLVE_A only */
415
-
416
464
  static ngx_int_t
417
465
  ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
418
466
  {
419
467
  uint32_t hash;
420
- in_addr_t addr, *addrs;
421
468
  ngx_int_t rc;
422
469
  ngx_uint_t naddrs;
470
+ ngx_addr_t *addrs;
423
471
  ngx_resolver_ctx_t *next;
424
472
  ngx_resolver_node_t *rn;
425
473
 
474
+ ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len);
475
+
426
476
  hash = ngx_crc32_short(ctx->name.data, ctx->name.len);
427
477
 
428
478
  rn = ngx_resolver_lookup_name(r, &ctx->name, hash);
@@ -439,22 +489,21 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
439
489
 
440
490
  ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
441
491
 
442
- naddrs = rn->naddrs;
492
+ naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
493
+ #if (NGX_HAVE_INET6)
494
+ naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
495
+ #endif
443
496
 
444
497
  if (naddrs) {
445
498
 
446
- /* NGX_RESOLVE_A answer */
499
+ if (naddrs == 1 && rn->naddrs == 1) {
500
+ addrs = NULL;
447
501
 
448
- if (naddrs != 1) {
449
- addr = 0;
450
- addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
502
+ } else {
503
+ addrs = ngx_resolver_export(r, rn, 1);
451
504
  if (addrs == NULL) {
452
505
  return NGX_ERROR;
453
506
  }
454
-
455
- } else {
456
- addr = rn->u.addr;
457
- addrs = NULL;
458
507
  }
459
508
 
460
509
  ctx->next = rn->waiting;
@@ -465,8 +514,19 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
465
514
  do {
466
515
  ctx->state = NGX_OK;
467
516
  ctx->naddrs = naddrs;
468
- ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
469
- ctx->addr = addr;
517
+
518
+ if (addrs == NULL) {
519
+ ctx->addrs = &ctx->addr;
520
+ ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
521
+ ctx->addr.socklen = sizeof(struct sockaddr_in);
522
+ ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
523
+ ctx->sin.sin_family = AF_INET;
524
+ ctx->sin.sin_addr.s_addr = rn->u.addr;
525
+
526
+ } else {
527
+ ctx->addrs = addrs;
528
+ }
529
+
470
530
  next = ctx->next;
471
531
 
472
532
  ctx->handler(ctx);
@@ -474,7 +534,8 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
474
534
  ctx = next;
475
535
  } while (ctx);
476
536
 
477
- if (addrs) {
537
+ if (addrs != NULL) {
538
+ ngx_resolver_free(r, addrs->sockaddr);
478
539
  ngx_resolver_free(r, addrs);
479
540
  }
480
541
 
@@ -524,16 +585,25 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
524
585
  if (rn->query) {
525
586
  ngx_resolver_free_locked(r, rn->query);
526
587
  rn->query = NULL;
588
+ #if (NGX_HAVE_INET6)
589
+ rn->query6 = NULL;
590
+ #endif
527
591
  }
528
592
 
529
593
  if (rn->cnlen) {
530
594
  ngx_resolver_free_locked(r, rn->u.cname);
531
595
  }
532
596
 
533
- if (rn->naddrs > 1) {
597
+ if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
534
598
  ngx_resolver_free_locked(r, rn->u.addrs);
535
599
  }
536
600
 
601
+ #if (NGX_HAVE_INET6)
602
+ if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
603
+ ngx_resolver_free_locked(r, rn->u6.addrs6);
604
+ }
605
+ #endif
606
+
537
607
  /* unlock alloc mutex */
538
608
 
539
609
  } else {
@@ -552,6 +622,9 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
552
622
  rn->node.key = hash;
553
623
  rn->nlen = (u_short) ctx->name.len;
554
624
  rn->query = NULL;
625
+ #if (NGX_HAVE_INET6)
626
+ rn->query6 = NULL;
627
+ #endif
555
628
 
556
629
  ngx_rbtree_insert(&r->name_rbtree, &rn->node);
557
630
  }
@@ -575,6 +648,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
575
648
  return NGX_OK;
576
649
  }
577
650
 
651
+ rn->naddrs = (u_short) -1;
652
+ #if (NGX_HAVE_INET6)
653
+ rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
654
+ #endif
655
+
578
656
  if (ngx_resolver_send_query(r, rn) != NGX_OK) {
579
657
  goto failed;
580
658
  }
@@ -601,9 +679,10 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
601
679
 
602
680
  ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
603
681
 
682
+ rn->code = 0;
604
683
  rn->cnlen = 0;
605
- rn->naddrs = 0;
606
684
  rn->valid = 0;
685
+ rn->ttl = NGX_MAX_UINT32_VALUE;
607
686
  rn->waiting = ctx;
608
687
 
609
688
  ctx->state = NGX_AGAIN;
@@ -630,16 +709,57 @@ ngx_int_t
630
709
  ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
631
710
  {
632
711
  u_char *name;
712
+ in_addr_t addr;
713
+ ngx_queue_t *resend_queue, *expire_queue;
714
+ ngx_rbtree_t *tree;
633
715
  ngx_resolver_t *r;
716
+ struct sockaddr_in *sin;
634
717
  ngx_resolver_node_t *rn;
718
+ #if (NGX_HAVE_INET6)
719
+ uint32_t hash;
720
+ struct sockaddr_in6 *sin6;
721
+ #endif
722
+
723
+ #if (NGX_SUPPRESS_WARN)
724
+ addr = 0;
725
+ #if (NGX_HAVE_INET6)
726
+ hash = 0;
727
+ sin6 = NULL;
728
+ #endif
729
+ #endif
635
730
 
636
731
  r = ctx->resolver;
637
732
 
638
- ctx->addr = ntohl(ctx->addr);
733
+ switch (ctx->addr.sockaddr->sa_family) {
639
734
 
640
- /* lock addr mutex */
735
+ #if (NGX_HAVE_INET6)
736
+ case AF_INET6:
737
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
738
+ hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
739
+
740
+ /* lock addr mutex */
741
+
742
+ rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
743
+
744
+ tree = &r->addr6_rbtree;
745
+ resend_queue = &r->addr6_resend_queue;
746
+ expire_queue = &r->addr6_expire_queue;
747
+
748
+ break;
749
+ #endif
750
+
751
+ default: /* AF_INET */
752
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
753
+ addr = ntohl(sin->sin_addr.s_addr);
754
+
755
+ /* lock addr mutex */
756
+
757
+ rn = ngx_resolver_lookup_addr(r, addr);
641
758
 
642
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
759
+ tree = &r->addr_rbtree;
760
+ resend_queue = &r->addr_resend_queue;
761
+ expire_queue = &r->addr_expire_queue;
762
+ }
643
763
 
644
764
  if (rn) {
645
765
 
@@ -651,7 +771,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
651
771
 
652
772
  rn->expire = ngx_time() + r->expire;
653
773
 
654
- ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
774
+ ngx_queue_insert_head(expire_queue, &rn->queue);
655
775
 
656
776
  name = ngx_resolver_dup(r, rn->name, rn->nlen);
657
777
  if (name == NULL) {
@@ -687,6 +807,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
687
807
 
688
808
  ngx_resolver_free(r, rn->query);
689
809
  rn->query = NULL;
810
+ #if (NGX_HAVE_INET6)
811
+ rn->query6 = NULL;
812
+ #endif
690
813
 
691
814
  } else {
692
815
  rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
@@ -694,16 +817,36 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
694
817
  goto failed;
695
818
  }
696
819
 
697
- rn->node.key = ctx->addr;
820
+ switch (ctx->addr.sockaddr->sa_family) {
821
+
822
+ #if (NGX_HAVE_INET6)
823
+ case AF_INET6:
824
+ rn->addr6 = sin6->sin6_addr;
825
+ rn->node.key = hash;
826
+ break;
827
+ #endif
828
+
829
+ default: /* AF_INET */
830
+ rn->node.key = addr;
831
+ }
832
+
698
833
  rn->query = NULL;
834
+ #if (NGX_HAVE_INET6)
835
+ rn->query6 = NULL;
836
+ #endif
699
837
 
700
- ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
838
+ ngx_rbtree_insert(tree, &rn->node);
701
839
  }
702
840
 
703
841
  if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
704
842
  goto failed;
705
843
  }
706
844
 
845
+ rn->naddrs = (u_short) -1;
846
+ #if (NGX_HAVE_INET6)
847
+ rn->naddrs6 = (u_short) -1;
848
+ #endif
849
+
707
850
  if (ngx_resolver_send_query(r, rn) != NGX_OK) {
708
851
  goto failed;
709
852
  }
@@ -720,19 +863,20 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
720
863
 
721
864
  ngx_add_timer(ctx->event, ctx->timeout);
722
865
 
723
- if (ngx_queue_empty(&r->addr_resend_queue)) {
866
+ if (ngx_queue_empty(resend_queue)) {
724
867
  ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
725
868
  }
726
869
 
727
870
  rn->expire = ngx_time() + r->resend_timeout;
728
871
 
729
- ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue);
872
+ ngx_queue_insert_head(resend_queue, &rn->queue);
730
873
 
874
+ rn->code = 0;
731
875
  rn->cnlen = 0;
732
- rn->naddrs = 0;
733
876
  rn->name = NULL;
734
877
  rn->nlen = 0;
735
878
  rn->valid = 0;
879
+ rn->ttl = NGX_MAX_UINT32_VALUE;
736
880
  rn->waiting = ctx;
737
881
 
738
882
  /* unlock addr mutex */
@@ -744,7 +888,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
744
888
  failed:
745
889
 
746
890
  if (rn) {
747
- ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
891
+ ngx_rbtree_delete(tree, &rn->node);
748
892
 
749
893
  if (rn->query) {
750
894
  ngx_resolver_free(r, rn->query);
@@ -769,12 +913,33 @@ void
769
913
  ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
770
914
  {
771
915
  in_addr_t addr;
916
+ ngx_queue_t *expire_queue;
917
+ ngx_rbtree_t *tree;
772
918
  ngx_resolver_t *r;
773
919
  ngx_resolver_ctx_t *w, **p;
920
+ struct sockaddr_in *sin;
774
921
  ngx_resolver_node_t *rn;
922
+ #if (NGX_HAVE_INET6)
923
+ uint32_t hash;
924
+ struct sockaddr_in6 *sin6;
925
+ #endif
775
926
 
776
927
  r = ctx->resolver;
777
928
 
929
+ switch (ctx->addr.sockaddr->sa_family) {
930
+
931
+ #if (NGX_HAVE_INET6)
932
+ case AF_INET6:
933
+ tree = &r->addr6_rbtree;
934
+ expire_queue = &r->addr6_expire_queue;
935
+ break;
936
+ #endif
937
+
938
+ default: /* AF_INET */
939
+ tree = &r->addr_rbtree;
940
+ expire_queue = &r->addr_expire_queue;
941
+ }
942
+
778
943
  ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
779
944
  "resolve addr done: %i", ctx->state);
780
945
 
@@ -786,7 +951,21 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
786
951
 
787
952
  if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
788
953
 
789
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
954
+ switch (ctx->addr.sockaddr->sa_family) {
955
+
956
+ #if (NGX_HAVE_INET6)
957
+ case AF_INET6:
958
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
959
+ hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
960
+ rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
961
+ break;
962
+ #endif
963
+
964
+ default: /* AF_INET */
965
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
966
+ addr = ntohl(sin->sin_addr.s_addr);
967
+ rn = ngx_resolver_lookup_addr(r, addr);
968
+ }
790
969
 
791
970
  if (rn) {
792
971
  p = &rn->waiting;
@@ -804,17 +983,22 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
804
983
  }
805
984
  }
806
985
 
807
- addr = ntohl(ctx->addr);
986
+ {
987
+ u_char text[NGX_SOCKADDR_STRLEN];
988
+ ngx_str_t addrtext;
989
+
990
+ addrtext.data = text;
991
+ addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
992
+ text, NGX_SOCKADDR_STRLEN, 0);
808
993
 
809
- ngx_log_error(NGX_LOG_ALERT, r->log, 0,
810
- "could not cancel %ud.%ud.%ud.%ud resolving",
811
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
812
- (addr >> 8) & 0xff, addr & 0xff);
994
+ ngx_log_error(NGX_LOG_ALERT, r->log, 0,
995
+ "could not cancel %V resolving", &addrtext);
996
+ }
813
997
  }
814
998
 
815
999
  done:
816
1000
 
817
- ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue);
1001
+ ngx_resolver_expire(r, tree, expire_queue);
818
1002
 
819
1003
  /* unlock addr mutex */
820
1004
 
@@ -896,16 +1080,33 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
896
1080
  uc->connection->read->resolver = 1;
897
1081
  }
898
1082
 
899
- n = ngx_send(uc->connection, rn->query, rn->qlen);
1083
+ if (rn->naddrs == (u_short) -1) {
1084
+ n = ngx_send(uc->connection, rn->query, rn->qlen);
900
1085
 
901
- if (n == -1) {
902
- return NGX_ERROR;
1086
+ if (n == -1) {
1087
+ return NGX_ERROR;
1088
+ }
1089
+
1090
+ if ((size_t) n != (size_t) rn->qlen) {
1091
+ ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1092
+ return NGX_ERROR;
1093
+ }
903
1094
  }
904
1095
 
905
- if ((size_t) n != (size_t) rn->qlen) {
906
- ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
907
- return NGX_ERROR;
1096
+ #if (NGX_HAVE_INET6)
1097
+ if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1098
+ n = ngx_send(uc->connection, rn->query6, rn->qlen);
1099
+
1100
+ if (n == -1) {
1101
+ return NGX_ERROR;
1102
+ }
1103
+
1104
+ if ((size_t) n != (size_t) rn->qlen) {
1105
+ ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1106
+ return NGX_ERROR;
1107
+ }
908
1108
  }
1109
+ #endif
909
1110
 
910
1111
  return NGX_OK;
911
1112
  }
@@ -915,6 +1116,9 @@ static void
915
1116
  ngx_resolver_resend_handler(ngx_event_t *ev)
916
1117
  {
917
1118
  time_t timer, atimer, ntimer;
1119
+ #if (NGX_HAVE_INET6)
1120
+ time_t a6timer;
1121
+ #endif
918
1122
  ngx_resolver_t *r;
919
1123
 
920
1124
  r = ev->data;
@@ -934,16 +1138,36 @@ ngx_resolver_resend_handler(ngx_event_t *ev)
934
1138
 
935
1139
  /* unlock addr mutex */
936
1140
 
937
- if (ntimer == 0) {
1141
+ #if (NGX_HAVE_INET6)
1142
+
1143
+ /* lock addr6 mutex */
1144
+
1145
+ a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);
1146
+
1147
+ /* unlock addr6 mutex */
1148
+
1149
+ #endif
1150
+
1151
+ timer = ntimer;
1152
+
1153
+ if (timer == 0) {
938
1154
  timer = atimer;
939
1155
 
940
- } else if (atimer == 0) {
941
- timer = ntimer;
1156
+ } else if (atimer) {
1157
+ timer = ngx_min(timer, atimer);
1158
+ }
1159
+
1160
+ #if (NGX_HAVE_INET6)
942
1161
 
943
- } else {
944
- timer = (atimer < ntimer) ? atimer : ntimer;
1162
+ if (timer == 0) {
1163
+ timer = a6timer;
1164
+
1165
+ } else if (a6timer) {
1166
+ timer = ngx_min(timer, a6timer);
945
1167
  }
946
1168
 
1169
+ #endif
1170
+
947
1171
  if (timer) {
948
1172
  ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
949
1173
  }
@@ -1021,39 +1245,42 @@ ngx_resolver_read_response(ngx_event_t *rev)
1021
1245
  static void
1022
1246
  ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
1023
1247
  {
1024
- char *err;
1025
- size_t len;
1026
- ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1027
- qtype, qclass;
1028
- ngx_queue_t *q;
1029
- ngx_resolver_qs_t *qs;
1030
- ngx_resolver_node_t *rn;
1031
- ngx_resolver_query_t *query;
1032
-
1033
- if ((size_t) n < sizeof(ngx_resolver_query_t)) {
1248
+ char *err;
1249
+ ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1250
+ qtype, qclass;
1251
+ #if (NGX_HAVE_INET6)
1252
+ ngx_uint_t qident6;
1253
+ #endif
1254
+ ngx_queue_t *q;
1255
+ ngx_resolver_qs_t *qs;
1256
+ ngx_resolver_hdr_t *response;
1257
+ ngx_resolver_node_t *rn;
1258
+
1259
+ if (n < sizeof(ngx_resolver_hdr_t)) {
1034
1260
  goto short_response;
1035
1261
  }
1036
1262
 
1037
- query = (ngx_resolver_query_t *) buf;
1263
+ response = (ngx_resolver_hdr_t *) buf;
1038
1264
 
1039
- ident = (query->ident_hi << 8) + query->ident_lo;
1040
- flags = (query->flags_hi << 8) + query->flags_lo;
1041
- nqs = (query->nqs_hi << 8) + query->nqs_lo;
1042
- nan = (query->nan_hi << 8) + query->nan_lo;
1265
+ ident = (response->ident_hi << 8) + response->ident_lo;
1266
+ flags = (response->flags_hi << 8) + response->flags_lo;
1267
+ nqs = (response->nqs_hi << 8) + response->nqs_lo;
1268
+ nan = (response->nan_hi << 8) + response->nan_lo;
1043
1269
 
1044
1270
  ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
1045
1271
  "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
1046
1272
  ident, flags, nqs, nan,
1047
- (query->nns_hi << 8) + query->nns_lo,
1048
- (query->nar_hi << 8) + query->nar_lo);
1273
+ (response->nns_hi << 8) + response->nns_lo,
1274
+ (response->nar_hi << 8) + response->nar_lo);
1049
1275
 
1050
- if (!(flags & 0x8000)) {
1276
+ /* response to a standard query */
1277
+ if ((flags & 0xf870) != 0x8000) {
1051
1278
  ngx_log_error(r->log_level, r->log, 0,
1052
1279
  "invalid DNS response %ui fl:%04Xui", ident, flags);
1053
1280
  return;
1054
1281
  }
1055
1282
 
1056
- code = flags & 0x7f;
1283
+ code = flags & 0xf;
1057
1284
 
1058
1285
  if (code == NGX_RESOLVE_FORMERR) {
1059
1286
 
@@ -1067,12 +1294,18 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
1067
1294
  qident = (rn->query[0] << 8) + rn->query[1];
1068
1295
 
1069
1296
  if (qident == ident) {
1070
- ngx_log_error(r->log_level, r->log, 0,
1071
- "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1072
- code, ngx_resolver_strerror(code), ident,
1073
- rn->nlen, rn->name);
1074
- return;
1297
+ goto dns_error_name;
1298
+ }
1299
+
1300
+ #if (NGX_HAVE_INET6)
1301
+ if (rn->query6) {
1302
+ qident6 = (rn->query6[0] << 8) + rn->query6[1];
1303
+
1304
+ if (qident6 == ident) {
1305
+ goto dns_error_name;
1306
+ }
1075
1307
  }
1308
+ #endif
1076
1309
  }
1077
1310
 
1078
1311
  goto dns_error;
@@ -1087,22 +1320,21 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
1087
1320
  goto done;
1088
1321
  }
1089
1322
 
1090
- i = sizeof(ngx_resolver_query_t);
1323
+ i = sizeof(ngx_resolver_hdr_t);
1091
1324
 
1092
1325
  while (i < (ngx_uint_t) n) {
1093
1326
  if (buf[i] == '\0') {
1094
1327
  goto found;
1095
1328
  }
1096
1329
 
1097
- len = buf[i];
1098
- i += 1 + len;
1330
+ i += 1 + buf[i];
1099
1331
  }
1100
1332
 
1101
1333
  goto short_response;
1102
1334
 
1103
1335
  found:
1104
1336
 
1105
- if (i++ == 0) {
1337
+ if (i++ == sizeof(ngx_resolver_hdr_t)) {
1106
1338
  err = "zero-length domain name in DNS response";
1107
1339
  goto done;
1108
1340
  }
@@ -1130,8 +1362,11 @@ found:
1130
1362
  switch (qtype) {
1131
1363
 
1132
1364
  case NGX_RESOLVE_A:
1365
+ #if (NGX_HAVE_INET6)
1366
+ case NGX_RESOLVE_AAAA:
1367
+ #endif
1133
1368
 
1134
- ngx_resolver_process_a(r, buf, n, ident, code, nan,
1369
+ ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
1135
1370
  i + sizeof(ngx_resolver_qs_t));
1136
1371
 
1137
1372
  break;
@@ -1152,7 +1387,7 @@ found:
1152
1387
 
1153
1388
  short_response:
1154
1389
 
1155
- err = "short dns response";
1390
+ err = "short DNS response";
1156
1391
 
1157
1392
  done:
1158
1393
 
@@ -1160,6 +1395,14 @@ done:
1160
1395
 
1161
1396
  return;
1162
1397
 
1398
+ dns_error_name:
1399
+
1400
+ ngx_log_error(r->log_level, r->log, 0,
1401
+ "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1402
+ code, ngx_resolver_strerror(code), ident,
1403
+ rn->nlen, rn->name);
1404
+ return;
1405
+
1163
1406
  dns_error:
1164
1407
 
1165
1408
  ngx_log_error(r->log_level, r->log, 0,
@@ -1171,21 +1414,29 @@ dns_error:
1171
1414
 
1172
1415
  static void
1173
1416
  ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1174
- ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans)
1417
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
1418
+ ngx_uint_t nan, ngx_uint_t ans)
1175
1419
  {
1176
1420
  char *err;
1177
1421
  u_char *cname;
1178
1422
  size_t len;
1179
1423
  int32_t ttl;
1180
1424
  uint32_t hash;
1181
- in_addr_t addr, *addrs;
1425
+ in_addr_t *addr;
1182
1426
  ngx_str_t name;
1183
- ngx_uint_t qtype, qident, naddrs, a, i, n, start;
1427
+ ngx_addr_t *addrs;
1428
+ ngx_uint_t type, class, qident, naddrs, a, i, n, start;
1429
+ #if (NGX_HAVE_INET6)
1430
+ struct in6_addr *addr6;
1431
+ #endif
1184
1432
  ngx_resolver_an_t *an;
1185
1433
  ngx_resolver_ctx_t *ctx, *next;
1186
1434
  ngx_resolver_node_t *rn;
1187
1435
 
1188
- if (ngx_resolver_copy(r, &name, buf, &buf[12], &buf[last]) != NGX_OK) {
1436
+ if (ngx_resolver_copy(r, &name, buf,
1437
+ buf + sizeof(ngx_resolver_hdr_t), buf + last)
1438
+ != NGX_OK)
1439
+ {
1189
1440
  return;
1190
1441
  }
1191
1442
 
@@ -1197,28 +1448,113 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1197
1448
 
1198
1449
  rn = ngx_resolver_lookup_name(r, &name, hash);
1199
1450
 
1200
- if (rn == NULL || rn->query == NULL) {
1451
+ if (rn == NULL) {
1201
1452
  ngx_log_error(r->log_level, r->log, 0,
1202
1453
  "unexpected response for %V", &name);
1454
+ ngx_resolver_free(r, name.data);
1203
1455
  goto failed;
1204
1456
  }
1205
1457
 
1206
- qident = (rn->query[0] << 8) + rn->query[1];
1458
+ switch (qtype) {
1459
+
1460
+ #if (NGX_HAVE_INET6)
1461
+ case NGX_RESOLVE_AAAA:
1462
+
1463
+ if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
1464
+ ngx_log_error(r->log_level, r->log, 0,
1465
+ "unexpected response for %V", &name);
1466
+ ngx_resolver_free(r, name.data);
1467
+ goto failed;
1468
+ }
1469
+
1470
+ rn->naddrs6 = 0;
1471
+ qident = (rn->query6[0] << 8) + rn->query6[1];
1472
+
1473
+ break;
1474
+ #endif
1475
+
1476
+ default: /* NGX_RESOLVE_A */
1477
+
1478
+ if (rn->query == NULL || rn->naddrs != (u_short) -1) {
1479
+ ngx_log_error(r->log_level, r->log, 0,
1480
+ "unexpected response for %V", &name);
1481
+ ngx_resolver_free(r, name.data);
1482
+ goto failed;
1483
+ }
1484
+
1485
+ rn->naddrs = 0;
1486
+ qident = (rn->query[0] << 8) + rn->query[1];
1487
+ }
1207
1488
 
1208
1489
  if (ident != qident) {
1209
1490
  ngx_log_error(r->log_level, r->log, 0,
1210
1491
  "wrong ident %ui response for %V, expect %ui",
1211
1492
  ident, &name, qident);
1493
+ ngx_resolver_free(r, name.data);
1212
1494
  goto failed;
1213
1495
  }
1214
1496
 
1215
1497
  ngx_resolver_free(r, name.data);
1216
1498
 
1499
+ if (code == 0 && rn->code) {
1500
+ code = rn->code;
1501
+ }
1502
+
1217
1503
  if (code == 0 && nan == 0) {
1218
- code = 3; /* NXDOMAIN */
1504
+
1505
+ #if (NGX_HAVE_INET6)
1506
+ switch (qtype) {
1507
+
1508
+ case NGX_RESOLVE_AAAA:
1509
+
1510
+ if (rn->naddrs == (u_short) -1) {
1511
+ goto next;
1512
+ }
1513
+
1514
+ if (rn->naddrs) {
1515
+ goto export;
1516
+ }
1517
+
1518
+ break;
1519
+
1520
+ default: /* NGX_RESOLVE_A */
1521
+
1522
+ if (rn->naddrs6 == (u_short) -1) {
1523
+ goto next;
1524
+ }
1525
+
1526
+ if (rn->naddrs6) {
1527
+ goto export;
1528
+ }
1529
+ }
1530
+ #endif
1531
+
1532
+ code = NGX_RESOLVE_NXDOMAIN;
1219
1533
  }
1220
1534
 
1221
1535
  if (code) {
1536
+
1537
+ #if (NGX_HAVE_INET6)
1538
+ switch (qtype) {
1539
+
1540
+ case NGX_RESOLVE_AAAA:
1541
+
1542
+ if (rn->naddrs == (u_short) -1) {
1543
+ rn->code = (u_char) code;
1544
+ goto next;
1545
+ }
1546
+
1547
+ break;
1548
+
1549
+ default: /* NGX_RESOLVE_A */
1550
+
1551
+ if (rn->naddrs6 == (u_short) -1) {
1552
+ rn->code = (u_char) code;
1553
+ goto next;
1554
+ }
1555
+ }
1556
+ #endif
1557
+
1222
1558
  next = rn->waiting;
1223
1559
  rn->waiting = NULL;
1224
1560
 
@@ -1231,11 +1567,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1231
1567
  /* unlock name mutex */
1232
1568
 
1233
1569
  while (next) {
1234
- ctx = next;
1235
- ctx->state = code;
1236
- next = ctx->next;
1570
+ ctx = next;
1571
+ ctx->state = code;
1572
+ next = ctx->next;
1237
1573
 
1238
- ctx->handler(ctx);
1574
+ ctx->handler(ctx);
1239
1575
  }
1240
1576
 
1241
1577
  return;
@@ -1243,11 +1579,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1243
1579
 
1244
1580
  i = ans;
1245
1581
  naddrs = 0;
1246
- addr = 0;
1247
- addrs = NULL;
1248
1582
  cname = NULL;
1249
- qtype = 0;
1250
- ttl = 0;
1251
1583
 
1252
1584
  for (a = 0; a < nan; a++) {
1253
1585
 
@@ -1273,7 +1605,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1273
1605
  test_length:
1274
1606
 
1275
1607
  if (i - start < 2) {
1276
- err = "invalid name in dns response";
1608
+ err = "invalid name in DNS response";
1277
1609
  goto invalid;
1278
1610
  }
1279
1611
 
@@ -1285,150 +1617,299 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1285
1617
 
1286
1618
  an = (ngx_resolver_an_t *) &buf[i];
1287
1619
 
1288
- qtype = (an->type_hi << 8) + an->type_lo;
1620
+ type = (an->type_hi << 8) + an->type_lo;
1621
+ class = (an->class_hi << 8) + an->class_lo;
1289
1622
  len = (an->len_hi << 8) + an->len_lo;
1290
1623
  ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
1291
1624
  + (an->ttl[2] << 8) + (an->ttl[3]);
1292
1625
 
1626
+ if (class != 1) {
1627
+ ngx_log_error(r->log_level, r->log, 0,
1628
+ "unexpected RR class %ui", class);
1629
+ goto failed;
1630
+ }
1631
+
1293
1632
  if (ttl < 0) {
1294
1633
  ttl = 0;
1295
1634
  }
1296
1635
 
1297
- if (qtype == NGX_RESOLVE_A) {
1636
+ rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);
1298
1637
 
1299
- i += sizeof(ngx_resolver_an_t);
1638
+ i += sizeof(ngx_resolver_an_t);
1300
1639
 
1301
- if (i + len > last) {
1640
+ switch (type) {
1641
+
1642
+ case NGX_RESOLVE_A:
1643
+
1644
+ if (qtype != NGX_RESOLVE_A) {
1645
+ err = "unexpected A record in DNS response";
1646
+ goto invalid;
1647
+ }
1648
+
1649
+ if (len != 4) {
1650
+ err = "invalid A record in DNS response";
1651
+ goto invalid;
1652
+ }
1653
+
1654
+ if (i + 4 > last) {
1302
1655
  goto short_response;
1303
1656
  }
1304
1657
 
1305
- addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1306
- + (buf[i + 2] << 8) + (buf[i + 3]));
1658
+ naddrs++;
1659
+
1660
+ break;
1661
+
1662
+ #if (NGX_HAVE_INET6)
1663
+ case NGX_RESOLVE_AAAA:
1664
+
1665
+ if (qtype != NGX_RESOLVE_AAAA) {
1666
+ err = "unexpected AAAA record in DNS response";
1667
+ goto invalid;
1668
+ }
1669
+
1670
+ if (len != 16) {
1671
+ err = "invalid AAAA record in DNS response";
1672
+ goto invalid;
1673
+ }
1674
+
1675
+ if (i + 16 > last) {
1676
+ goto short_response;
1677
+ }
1307
1678
 
1308
1679
  naddrs++;
1309
1680
 
1310
- i += len;
1681
+ break;
1682
+ #endif
1311
1683
 
1312
- } else if (qtype == NGX_RESOLVE_CNAME) {
1313
- cname = &buf[i] + sizeof(ngx_resolver_an_t);
1314
- i += sizeof(ngx_resolver_an_t) + len;
1684
+ case NGX_RESOLVE_CNAME:
1315
1685
 
1316
- } else if (qtype == NGX_RESOLVE_DNAME) {
1317
- i += sizeof(ngx_resolver_an_t) + len;
1686
+ cname = &buf[i];
1687
+
1688
+ break;
1689
+
1690
+ case NGX_RESOLVE_DNAME:
1691
+
1692
+ break;
1693
+
1694
+ default:
1318
1695
 
1319
- } else {
1320
1696
  ngx_log_error(r->log_level, r->log, 0,
1321
- "unexpected qtype %ui", qtype);
1697
+ "unexpected RR type %ui", type);
1322
1698
  }
1699
+
1700
+ i += len;
1323
1701
  }
1324
1702
 
1325
1703
  ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1326
- "resolver naddrs:%ui cname:%p ttl:%d",
1327
- naddrs, cname, ttl);
1704
+ "resolver naddrs:%ui cname:%p ttl:%uD",
1705
+ naddrs, cname, rn->ttl);
1328
1706
 
1329
1707
  if (naddrs) {
1330
1708
 
1331
- if (naddrs == 1) {
1332
- rn->u.addr = addr;
1709
+ switch (qtype) {
1333
1710
 
1334
- } else {
1711
+ #if (NGX_HAVE_INET6)
1712
+ case NGX_RESOLVE_AAAA:
1335
1713
 
1336
- addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1337
- if (addrs == NULL) {
1338
- return;
1339
- }
1714
+ if (naddrs == 1) {
1715
+ addr6 = &rn->u6.addr6;
1716
+ rn->naddrs6 = 1;
1340
1717
 
1341
- n = 0;
1342
- i = ans;
1718
+ } else {
1719
+ addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
1720
+ if (addr6 == NULL) {
1721
+ goto failed;
1722
+ }
1343
1723
 
1344
- for (a = 0; a < nan; a++) {
1724
+ rn->u6.addrs6 = addr6;
1725
+ rn->naddrs6 = (u_short) naddrs;
1726
+ }
1345
1727
 
1346
- for ( ;; ) {
1728
+ #if (NGX_SUPPRESS_WARN)
1729
+ addr = NULL;
1730
+ #endif
1347
1731
 
1348
- if (buf[i] & 0xc0) {
1349
- i += 2;
1350
- goto ok;
1351
- }
1732
+ break;
1733
+ #endif
1352
1734
 
1353
- if (buf[i] == 0) {
1354
- i++;
1355
- goto ok;
1356
- }
1735
+ default: /* NGX_RESOLVE_A */
1736
+
1737
+ if (naddrs == 1) {
1738
+ addr = &rn->u.addr;
1739
+ rn->naddrs = 1;
1357
1740
 
1358
- i += 1 + buf[i];
1741
+ } else {
1742
+ addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1743
+ if (addr == NULL) {
1744
+ goto failed;
1359
1745
  }
1360
1746
 
1361
- ok:
1747
+ rn->u.addrs = addr;
1748
+ rn->naddrs = (u_short) naddrs;
1749
+ }
1362
1750
 
1363
- an = (ngx_resolver_an_t *) &buf[i];
1751
+ #if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
1752
+ addr6 = NULL;
1753
+ #endif
1754
+ }
1364
1755
 
1365
- qtype = (an->type_hi << 8) + an->type_lo;
1366
- len = (an->len_hi << 8) + an->len_lo;
1756
+ n = 0;
1757
+ i = ans;
1367
1758
 
1368
- i += sizeof(ngx_resolver_an_t);
1759
+ for (a = 0; a < nan; a++) {
1369
1760
 
1370
- if (qtype == NGX_RESOLVE_A) {
1761
+ for ( ;; ) {
1371
1762
 
1372
- addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1373
- + (buf[i + 2] << 8) + (buf[i + 3]));
1763
+ if (buf[i] & 0xc0) {
1764
+ i += 2;
1765
+ break;
1766
+ }
1374
1767
 
1375
- if (n == naddrs) {
1376
- break;
1377
- }
1768
+ if (buf[i] == 0) {
1769
+ i++;
1770
+ break;
1378
1771
  }
1379
1772
 
1380
- i += len;
1773
+ i += 1 + buf[i];
1381
1774
  }
1382
1775
 
1383
- rn->u.addrs = addrs;
1776
+ an = (ngx_resolver_an_t *) &buf[i];
1384
1777
 
1385
- addrs = ngx_resolver_dup(r, rn->u.addrs,
1386
- naddrs * sizeof(in_addr_t));
1387
- if (addrs == NULL) {
1388
- return;
1389
- }
1390
- }
1778
+ type = (an->type_hi << 8) + an->type_lo;
1779
+ len = (an->len_hi << 8) + an->len_lo;
1391
1780
 
1392
- rn->naddrs = (u_short) naddrs;
1781
+ i += sizeof(ngx_resolver_an_t);
1393
1782
 
1394
- ngx_queue_remove(&rn->queue);
1783
+ if (type == NGX_RESOLVE_A) {
1395
1784
 
1396
- rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
1397
- rn->expire = ngx_time() + r->expire;
1785
+ addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1786
+ + (buf[i + 2] << 8) + (buf[i + 3]));
1398
1787
 
1399
- ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1788
+ if (++n == naddrs) {
1400
1789
 
1401
- next = rn->waiting;
1402
- rn->waiting = NULL;
1790
+ #if (NGX_HAVE_INET6)
1791
+ if (rn->naddrs6 == (u_short) -1) {
1792
+ goto next;
1793
+ }
1794
+ #endif
1403
1795
 
1404
- /* unlock name mutex */
1796
+ break;
1797
+ }
1798
+ }
1405
1799
 
1406
- while (next) {
1407
- ctx = next;
1408
- ctx->state = NGX_OK;
1409
- ctx->naddrs = naddrs;
1410
- ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
1411
- ctx->addr = addr;
1412
- next = ctx->next;
1800
+ #if (NGX_HAVE_INET6)
1801
+ else if (type == NGX_RESOLVE_AAAA) {
1413
1802
 
1414
- ctx->handler(ctx);
1415
- }
1803
+ ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);
1416
1804
 
1417
- if (naddrs > 1) {
1418
- ngx_resolver_free(r, addrs);
1419
- }
1805
+ if (++n == naddrs) {
1420
1806
 
1421
- ngx_resolver_free(r, rn->query);
1807
+ if (rn->naddrs == (u_short) -1) {
1808
+ goto next;
1809
+ }
1810
+
1811
+ break;
1812
+ }
1813
+ }
1814
+ #endif
1815
+
1816
+ i += len;
1817
+ }
1818
+ }
1819
+
1820
+ if (rn->naddrs != (u_short) -1
1821
+ #if (NGX_HAVE_INET6)
1822
+ && rn->naddrs6 != (u_short) -1
1823
+ #endif
1824
+ && rn->naddrs
1825
+ #if (NGX_HAVE_INET6)
1826
+ + rn->naddrs6
1827
+ #endif
1828
+ > 0)
1829
+ {
1830
+
1831
+ #if (NGX_HAVE_INET6)
1832
+ export:
1833
+ #endif
1834
+
1835
+ naddrs = rn->naddrs;
1836
+ #if (NGX_HAVE_INET6)
1837
+ naddrs += rn->naddrs6;
1838
+ #endif
1839
+
1840
+ if (naddrs == 1 && rn->naddrs == 1) {
1841
+ addrs = NULL;
1842
+
1843
+ } else {
1844
+ addrs = ngx_resolver_export(r, rn, 0);
1845
+ if (addrs == NULL) {
1846
+ goto failed;
1847
+ }
1848
+ }
1849
+
1850
+ ngx_queue_remove(&rn->queue);
1851
+
1852
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
1853
+ rn->expire = ngx_time() + r->expire;
1854
+
1855
+ ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1856
+
1857
+ next = rn->waiting;
1858
+ rn->waiting = NULL;
1859
+
1860
+ /* unlock name mutex */
1861
+
1862
+ while (next) {
1863
+ ctx = next;
1864
+ ctx->state = NGX_OK;
1865
+ ctx->naddrs = naddrs;
1866
+
1867
+ if (addrs == NULL) {
1868
+ ctx->addrs = &ctx->addr;
1869
+ ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
1870
+ ctx->addr.socklen = sizeof(struct sockaddr_in);
1871
+ ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
1872
+ ctx->sin.sin_family = AF_INET;
1873
+ ctx->sin.sin_addr.s_addr = rn->u.addr;
1874
+
1875
+ } else {
1876
+ ctx->addrs = addrs;
1877
+ }
1878
+
1879
+ next = ctx->next;
1880
+
1881
+ ctx->handler(ctx);
1882
+ }
1883
+
1884
+ if (addrs != NULL) {
1885
+ ngx_resolver_free(r, addrs->sockaddr);
1886
+ ngx_resolver_free(r, addrs);
1887
+ }
1888
+
1889
+ ngx_resolver_free(r, rn->query);
1422
1890
  rn->query = NULL;
1891
+ #if (NGX_HAVE_INET6)
1892
+ rn->query6 = NULL;
1893
+ #endif
1423
1894
 
1424
1895
  return;
1896
+ }
1425
1897
 
1426
- } else if (cname) {
1898
+ if (cname) {
1427
1899
 
1428
1900
  /* CNAME only */
1429
1901
 
1430
- if (ngx_resolver_copy(r, &name, buf, cname, &buf[last]) != NGX_OK) {
1431
- return;
1902
+ if (rn->naddrs == (u_short) -1
1903
+ #if (NGX_HAVE_INET6)
1904
+ || rn->naddrs6 == (u_short) -1
1905
+ #endif
1906
+ )
1907
+ {
1908
+ goto next;
1909
+ }
1910
+
1911
+ if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
1912
+ goto failed;
1432
1913
  }
1433
1914
 
1434
1915
  ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
@@ -1439,7 +1920,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1439
1920
  rn->cnlen = (u_short) name.len;
1440
1921
  rn->u.cname = name.data;
1441
1922
 
1442
- rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
1923
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
1443
1924
  rn->expire = ngx_time() + r->expire;
1444
1925
 
1445
1926
  ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
@@ -1455,18 +1936,22 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1455
1936
 
1456
1937
  ngx_resolver_free(r, rn->query);
1457
1938
  rn->query = NULL;
1939
+ #if (NGX_HAVE_INET6)
1940
+ rn->query6 = NULL;
1941
+ #endif
1942
+
1943
+ /* unlock name mutex */
1458
1944
 
1459
1945
  return;
1460
1946
  }
1461
1947
 
1462
1948
  ngx_log_error(r->log_level, r->log, 0,
1463
- "no A or CNAME types in DNS responses, unknown query type: %ui",
1464
- qtype);
1949
+ "no A or CNAME types in DNS response");
1465
1950
  return;
1466
1951
 
1467
1952
  short_response:
1468
1953
 
1469
- err = "short dns response";
1954
+ err = "short DNS response";
1470
1955
 
1471
1956
  invalid:
1472
1957
 
@@ -1478,9 +1963,9 @@ invalid:
1478
1963
 
1479
1964
  failed:
1480
1965
 
1481
- /* unlock name mutex */
1966
+ next:
1482
1967
 
1483
- ngx_resolver_free(r, name.data);
1968
+ /* unlock name mutex */
1484
1969
 
1485
1970
  return;
1486
1971
  }
@@ -1492,47 +1977,123 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1492
1977
  {
1493
1978
  char *err;
1494
1979
  size_t len;
1980
+ u_char text[NGX_SOCKADDR_STRLEN];
1495
1981
  in_addr_t addr;
1496
1982
  int32_t ttl;
1497
- ngx_int_t digit;
1983
+ ngx_int_t octet;
1498
1984
  ngx_str_t name;
1499
- ngx_uint_t i, mask, qident;
1985
+ ngx_uint_t i, mask, qident, class;
1986
+ ngx_queue_t *expire_queue;
1987
+ ngx_rbtree_t *tree;
1500
1988
  ngx_resolver_an_t *an;
1501
1989
  ngx_resolver_ctx_t *ctx, *next;
1502
1990
  ngx_resolver_node_t *rn;
1991
+ #if (NGX_HAVE_INET6)
1992
+ uint32_t hash;
1993
+ ngx_int_t digit;
1994
+ struct in6_addr addr6;
1995
+ #endif
1503
1996
 
1504
- if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) {
1505
- goto invalid_in_addr_arpa;
1997
+ if (ngx_resolver_copy(r, NULL, buf,
1998
+ buf + sizeof(ngx_resolver_hdr_t), buf + n)
1999
+ != NGX_OK)
2000
+ {
2001
+ return;
1506
2002
  }
1507
2003
 
2004
+ /* AF_INET */
2005
+
1508
2006
  addr = 0;
1509
- i = 12;
2007
+ i = sizeof(ngx_resolver_hdr_t);
1510
2008
 
1511
2009
  for (mask = 0; mask < 32; mask += 8) {
1512
2010
  len = buf[i++];
1513
2011
 
1514
- digit = ngx_atoi(&buf[i], len);
1515
- if (digit == NGX_ERROR || digit > 255) {
2012
+ octet = ngx_atoi(&buf[i], len);
2013
+ if (octet == NGX_ERROR || octet > 255) {
1516
2014
  goto invalid_in_addr_arpa;
1517
2015
  }
1518
2016
 
1519
- addr += digit << mask;
2017
+ addr += octet << mask;
1520
2018
  i += len;
1521
2019
  }
1522
2020
 
1523
- if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) {
1524
- goto invalid_in_addr_arpa;
2021
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
2022
+ i += sizeof("\7in-addr\4arpa");
2023
+
2024
+ /* lock addr mutex */
2025
+
2026
+ rn = ngx_resolver_lookup_addr(r, addr);
2027
+
2028
+ tree = &r->addr_rbtree;
2029
+ expire_queue = &r->addr_expire_queue;
2030
+
2031
+ addr = htonl(addr);
2032
+ name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
2033
+ name.data = text;
2034
+
2035
+ goto valid;
2036
+ }
2037
+
2038
+ invalid_in_addr_arpa:
2039
+
2040
+ #if (NGX_HAVE_INET6)
2041
+
2042
+ i = sizeof(ngx_resolver_hdr_t);
2043
+
2044
+ for (octet = 15; octet >= 0; octet--) {
2045
+ if (buf[i++] != '\1') {
2046
+ goto invalid_ip6_arpa;
2047
+ }
2048
+
2049
+ digit = ngx_hextoi(&buf[i++], 1);
2050
+ if (digit == NGX_ERROR) {
2051
+ goto invalid_ip6_arpa;
2052
+ }
2053
+
2054
+ addr6.s6_addr[octet] = (u_char) digit;
2055
+
2056
+ if (buf[i++] != '\1') {
2057
+ goto invalid_ip6_arpa;
2058
+ }
2059
+
2060
+ digit = ngx_hextoi(&buf[i++], 1);
2061
+ if (digit == NGX_ERROR) {
2062
+ goto invalid_ip6_arpa;
2063
+ }
2064
+
2065
+ addr6.s6_addr[octet] += (u_char) (digit * 16);
1525
2066
  }
1526
2067
 
1527
- /* lock addr mutex */
2068
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
2069
+ i += sizeof("\3ip6\4arpa");
2070
+
2071
+ /* lock addr mutex */
2072
+
2073
+ hash = ngx_crc32_short(addr6.s6_addr, 16);
2074
+ rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
2075
+
2076
+ tree = &r->addr6_rbtree;
2077
+ expire_queue = &r->addr6_expire_queue;
2078
+
2079
+ name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
2080
+ name.data = text;
2081
+
2082
+ goto valid;
2083
+ }
2084
+
2085
+ invalid_ip6_arpa:
2086
+ #endif
1528
2087
 
1529
- rn = ngx_resolver_lookup_addr(r, addr);
2088
+ ngx_log_error(r->log_level, r->log, 0,
2089
+ "invalid in-addr.arpa or ip6.arpa name in DNS response");
2090
+ return;
2091
+
2092
+ valid:
1530
2093
 
1531
2094
  if (rn == NULL || rn->query == NULL) {
1532
2095
  ngx_log_error(r->log_level, r->log, 0,
1533
- "unexpected response for %ud.%ud.%ud.%ud",
1534
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
1535
- (addr >> 8) & 0xff, addr & 0xff);
2096
+ "unexpected response for %V", &name);
1536
2097
  goto failed;
1537
2098
  }
1538
2099
 
@@ -1540,14 +2101,13 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1540
2101
 
1541
2102
  if (ident != qident) {
1542
2103
  ngx_log_error(r->log_level, r->log, 0,
1543
- "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
1544
- ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff,
1545
- (addr >> 8) & 0xff, addr & 0xff, qident);
2104
+ "wrong ident %ui response for %V, expect %ui",
2105
+ ident, &name, qident);
1546
2106
  goto failed;
1547
2107
  }
1548
2108
 
1549
2109
  if (code == 0 && nan == 0) {
1550
- code = 3; /* NXDOMAIN */
2110
+ code = NGX_RESOLVE_NXDOMAIN;
1551
2111
  }
1552
2112
 
1553
2113
  if (code) {
@@ -1556,42 +2116,49 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1556
2116
 
1557
2117
  ngx_queue_remove(&rn->queue);
1558
2118
 
1559
- ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
2119
+ ngx_rbtree_delete(tree, &rn->node);
1560
2120
 
1561
2121
  ngx_resolver_free_node(r, rn);
1562
2122
 
1563
2123
  /* unlock addr mutex */
1564
2124
 
1565
2125
  while (next) {
1566
- ctx = next;
1567
- ctx->state = code;
1568
- next = ctx->next;
2126
+ ctx = next;
2127
+ ctx->state = code;
2128
+ next = ctx->next;
1569
2129
 
1570
- ctx->handler(ctx);
2130
+ ctx->handler(ctx);
1571
2131
  }
1572
2132
 
1573
2133
  return;
1574
2134
  }
1575
2135
 
1576
- i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);
2136
+ i += sizeof(ngx_resolver_qs_t);
1577
2137
 
1578
- if (i + 2 + sizeof(ngx_resolver_an_t) > (ngx_uint_t) n) {
2138
+ if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
1579
2139
  goto short_response;
1580
2140
  }
1581
2141
 
1582
- /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
2142
+ /* compression pointer to *.arpa */
1583
2143
 
1584
- if (buf[i] != 0xc0 || buf[i + 1] != 0x0c) {
1585
- err = "invalid in-addr.arpa name in DNS response";
2144
+ if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
2145
+ err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
1586
2146
  goto invalid;
1587
2147
  }
1588
2148
 
1589
2149
  an = (ngx_resolver_an_t *) &buf[i + 2];
1590
2150
 
2151
+ class = (an->class_hi << 8) + an->class_lo;
1591
2152
  len = (an->len_hi << 8) + an->len_lo;
1592
2153
  ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
1593
2154
  + (an->ttl[2] << 8) + (an->ttl[3]);
1594
2155
 
2156
+ if (class != 1) {
2157
+ ngx_log_error(r->log_level, r->log, 0,
2158
+ "unexpected RR class %ui", class);
2159
+ goto failed;
2160
+ }
2161
+
1595
2162
  if (ttl < 0) {
1596
2163
  ttl = 0;
1597
2164
  }
@@ -1599,16 +2166,16 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1599
2166
  ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1600
2167
  "resolver qt:%ui cl:%ui len:%uz",
1601
2168
  (an->type_hi << 8) + an->type_lo,
1602
- (an->class_hi << 8) + an->class_lo, len);
2169
+ class, len);
1603
2170
 
1604
2171
  i += 2 + sizeof(ngx_resolver_an_t);
1605
2172
 
1606
- if (i + len > (ngx_uint_t) n) {
2173
+ if (i + len > n) {
1607
2174
  goto short_response;
1608
2175
  }
1609
2176
 
1610
- if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) {
1611
- return;
2177
+ if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
2178
+ goto failed;
1612
2179
  }
1613
2180
 
1614
2181
  ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);
@@ -1634,7 +2201,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1634
2201
  rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
1635
2202
  rn->expire = ngx_time() + r->expire;
1636
2203
 
1637
- ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
2204
+ ngx_queue_insert_head(expire_queue, &rn->queue);
1638
2205
 
1639
2206
  next = rn->waiting;
1640
2207
  rn->waiting = NULL;
@@ -1642,24 +2209,18 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1642
2209
  /* unlock addr mutex */
1643
2210
 
1644
2211
  while (next) {
1645
- ctx = next;
1646
- ctx->state = NGX_OK;
1647
- ctx->name = name;
1648
- next = ctx->next;
2212
+ ctx = next;
2213
+ ctx->state = NGX_OK;
2214
+ ctx->name = name;
2215
+ next = ctx->next;
1649
2216
 
1650
- ctx->handler(ctx);
2217
+ ctx->handler(ctx);
1651
2218
  }
1652
2219
 
1653
2220
  ngx_resolver_free(r, name.data);
1654
2221
 
1655
2222
  return;
1656
2223
 
1657
- invalid_in_addr_arpa:
1658
-
1659
- ngx_log_error(r->log_level, r->log, 0,
1660
- "invalid in-addr.arpa name in DNS response");
1661
- return;
1662
-
1663
2224
  short_response:
1664
2225
 
1665
2226
  err = "short DNS response";
@@ -1752,6 +2313,52 @@ ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
1752
2313
  }
1753
2314
 
1754
2315
 
2316
+ #if (NGX_HAVE_INET6)
2317
+
2318
+ static ngx_resolver_node_t *
2319
+ ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
2320
+ uint32_t hash)
2321
+ {
2322
+ ngx_int_t rc;
2323
+ ngx_rbtree_node_t *node, *sentinel;
2324
+ ngx_resolver_node_t *rn;
2325
+
2326
+ node = r->addr6_rbtree.root;
2327
+ sentinel = r->addr6_rbtree.sentinel;
2328
+
2329
+ while (node != sentinel) {
2330
+
2331
+ if (hash < node->key) {
2332
+ node = node->left;
2333
+ continue;
2334
+ }
2335
+
2336
+ if (hash > node->key) {
2337
+ node = node->right;
2338
+ continue;
2339
+ }
2340
+
2341
+ /* hash == node->key */
2342
+
2343
+ rn = (ngx_resolver_node_t *) node;
2344
+
2345
+ rc = ngx_memcmp(addr, &rn->addr6, 16);
2346
+
2347
+ if (rc == 0) {
2348
+ return rn;
2349
+ }
2350
+
2351
+ node = (rc < 0) ? node->left : node->right;
2352
+ }
2353
+
2354
+ /* not found */
2355
+
2356
+ return NULL;
2357
+ }
2358
+
2359
+ #endif
2360
+
2361
+
1755
2362
  static void
1756
2363
  ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
1757
2364
  ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
@@ -1793,20 +2400,74 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
1793
2400
  }
1794
2401
 
1795
2402
 
2403
+ #if (NGX_HAVE_INET6)
2404
+
2405
+ static void
2406
+ ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
2407
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
2408
+ {
2409
+ ngx_rbtree_node_t **p;
2410
+ ngx_resolver_node_t *rn, *rn_temp;
2411
+
2412
+ for ( ;; ) {
2413
+
2414
+ if (node->key < temp->key) {
2415
+
2416
+ p = &temp->left;
2417
+
2418
+ } else if (node->key > temp->key) {
2419
+
2420
+ p = &temp->right;
2421
+
2422
+ } else { /* node->key == temp->key */
2423
+
2424
+ rn = (ngx_resolver_node_t *) node;
2425
+ rn_temp = (ngx_resolver_node_t *) temp;
2426
+
2427
+ p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
2428
+ < 0) ? &temp->left : &temp->right;
2429
+ }
2430
+
2431
+ if (*p == sentinel) {
2432
+ break;
2433
+ }
2434
+
2435
+ temp = *p;
2436
+ }
2437
+
2438
+ *p = node;
2439
+ node->parent = temp;
2440
+ node->left = sentinel;
2441
+ node->right = sentinel;
2442
+ ngx_rbt_red(node);
2443
+ }
2444
+
2445
+ #endif
2446
+
2447
+
1796
2448
  static ngx_int_t
1797
2449
  ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1798
2450
  {
1799
- u_char *p, *s;
1800
- size_t len, nlen;
1801
- ngx_uint_t ident;
1802
- ngx_resolver_qs_t *qs;
1803
- ngx_resolver_query_t *query;
2451
+ u_char *p, *s;
2452
+ size_t len, nlen;
2453
+ ngx_uint_t ident;
2454
+ #if (NGX_HAVE_INET6)
2455
+ ngx_resolver_t *r;
2456
+ #endif
2457
+ ngx_resolver_qs_t *qs;
2458
+ ngx_resolver_hdr_t *query;
1804
2459
 
1805
2460
  nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
1806
2461
 
1807
- len = sizeof(ngx_resolver_query_t) + nlen + sizeof(ngx_resolver_qs_t);
2462
+ len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
1808
2463
 
2464
+ #if (NGX_HAVE_INET6)
2465
+ r = ctx->resolver;
2466
+
2467
+ p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len);
2468
+ #else
1809
2469
  p = ngx_resolver_alloc(ctx->resolver, len);
2470
+ #endif
1810
2471
  if (p == NULL) {
1811
2472
  return NGX_ERROR;
1812
2473
  }
@@ -1814,12 +2475,18 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1814
2475
  rn->qlen = (u_short) len;
1815
2476
  rn->query = p;
1816
2477
 
1817
- query = (ngx_resolver_query_t *) p;
2478
+ #if (NGX_HAVE_INET6)
2479
+ if (r->ipv6) {
2480
+ rn->query6 = p + len;
2481
+ }
2482
+ #endif
2483
+
2484
+ query = (ngx_resolver_hdr_t *) p;
1818
2485
 
1819
2486
  ident = ngx_random();
1820
2487
 
1821
2488
  ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
1822
- "resolve: \"%V\" %i", &ctx->name, ident & 0xffff);
2489
+ "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff);
1823
2490
 
1824
2491
  query->ident_hi = (u_char) ((ident >> 8) & 0xff);
1825
2492
  query->ident_lo = (u_char) (ident & 0xff);
@@ -1833,14 +2500,14 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1833
2500
  query->nns_hi = 0; query->nns_lo = 0;
1834
2501
  query->nar_hi = 0; query->nar_lo = 0;
1835
2502
 
1836
- p += sizeof(ngx_resolver_query_t) + nlen;
2503
+ p += sizeof(ngx_resolver_hdr_t) + nlen;
1837
2504
 
1838
2505
  qs = (ngx_resolver_qs_t *) p;
1839
2506
 
1840
2507
  /* query type */
1841
- qs->type_hi = 0; qs->type_lo = (u_char) ctx->type;
2508
+ qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;
1842
2509
 
1843
- /* IP query class */
2510
+ /* IN query class */
1844
2511
  qs->class_hi = 0; qs->class_lo = 1;
1845
2512
 
1846
2513
  /* convert "www.example.com" to "\3www\7example\3com\0" */
@@ -1876,24 +2543,66 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1876
2543
 
1877
2544
  *p = (u_char) len;
1878
2545
 
2546
+ #if (NGX_HAVE_INET6)
2547
+ if (!r->ipv6) {
2548
+ return NGX_OK;
2549
+ }
2550
+
2551
+ p = rn->query6;
2552
+
2553
+ ngx_memcpy(p, rn->query, rn->qlen);
2554
+
2555
+ query = (ngx_resolver_hdr_t *) p;
2556
+
2557
+ ident = ngx_random();
2558
+
2559
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
2560
+ "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff);
2561
+
2562
+ query->ident_hi = (u_char) ((ident >> 8) & 0xff);
2563
+ query->ident_lo = (u_char) (ident & 0xff);
2564
+
2565
+ p += sizeof(ngx_resolver_hdr_t) + nlen;
2566
+
2567
+ qs = (ngx_resolver_qs_t *) p;
2568
+
2569
+ qs->type_lo = NGX_RESOLVE_AAAA;
2570
+ #endif
2571
+
1879
2572
  return NGX_OK;
1880
2573
  }
1881
2574
 
1882
2575
 
1883
- /* AF_INET only */
1884
-
1885
2576
  static ngx_int_t
1886
2577
  ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1887
2578
  {
1888
- u_char *p, *d;
1889
- size_t len;
1890
- ngx_int_t n;
1891
- ngx_uint_t ident;
1892
- ngx_resolver_query_t *query;
2579
+ u_char *p, *d;
2580
+ size_t len;
2581
+ in_addr_t addr;
2582
+ ngx_int_t n;
2583
+ ngx_uint_t ident;
2584
+ ngx_resolver_hdr_t *query;
2585
+ struct sockaddr_in *sin;
2586
+ #if (NGX_HAVE_INET6)
2587
+ struct sockaddr_in6 *sin6;
2588
+ #endif
2589
+
2590
+ switch (ctx->addr.sockaddr->sa_family) {
1893
2591
 
1894
- len = sizeof(ngx_resolver_query_t)
1895
- + sizeof(".255.255.255.255.in-addr.arpa.") - 1
1896
- + sizeof(ngx_resolver_qs_t);
2592
+ #if (NGX_HAVE_INET6)
2593
+ case AF_INET6:
2594
+ len = sizeof(ngx_resolver_hdr_t)
2595
+ + 64 + sizeof(".ip6.arpa.") - 1
2596
+ + sizeof(ngx_resolver_qs_t);
2597
+
2598
+ break;
2599
+ #endif
2600
+
2601
+ default: /* AF_INET */
2602
+ len = sizeof(ngx_resolver_hdr_t)
2603
+ + sizeof(".255.255.255.255.in-addr.arpa.") - 1
2604
+ + sizeof(ngx_resolver_qs_t);
2605
+ }
1897
2606
 
1898
2607
  p = ngx_resolver_alloc(ctx->resolver, len);
1899
2608
  if (p == NULL) {
@@ -1901,7 +2610,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1901
2610
  }
1902
2611
 
1903
2612
  rn->query = p;
1904
- query = (ngx_resolver_query_t *) p;
2613
+ query = (ngx_resolver_hdr_t *) p;
1905
2614
 
1906
2615
  ident = ngx_random();
1907
2616
 
@@ -1917,20 +2626,43 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
1917
2626
  query->nns_hi = 0; query->nns_lo = 0;
1918
2627
  query->nar_hi = 0; query->nar_lo = 0;
1919
2628
 
1920
- p += sizeof(ngx_resolver_query_t);
2629
+ p += sizeof(ngx_resolver_hdr_t);
2630
+
2631
+ switch (ctx->addr.sockaddr->sa_family) {
1921
2632
 
1922
- for (n = 0; n < 32; n += 8) {
1923
- d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
1924
- *p = (u_char) (d - &p[1]);
1925
- p = d;
2633
+ #if (NGX_HAVE_INET6)
2634
+ case AF_INET6:
2635
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
2636
+
2637
+ for (n = 15; n >= 0; n--) {
2638
+ p = ngx_sprintf(p, "\1%xd\1%xd",
2639
+ sin6->sin6_addr.s6_addr[n] & 0xf,
2640
+ (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
2641
+ }
2642
+
2643
+ p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);
2644
+
2645
+ break;
2646
+ #endif
2647
+
2648
+ default: /* AF_INET */
2649
+
2650
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
2651
+ addr = ntohl(sin->sin_addr.s_addr);
2652
+
2653
+ for (n = 0; n < 32; n += 8) {
2654
+ d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff);
2655
+ *p = (u_char) (d - &p[1]);
2656
+ p = d;
2657
+ }
2658
+
2659
+ p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
1926
2660
  }
1927
2661
 
1928
- /* query type "PTR", IP query class */
1929
- ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
2662
+ /* query type "PTR", IN query class */
2663
+ p = ngx_cpymem(p, "\0\14\0\1", 4);
1930
2664
 
1931
- rn->qlen = (u_short)
1932
- (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)
1933
- - rn->query);
2665
+ rn->qlen = (u_short) (p - rn->query);
1934
2666
 
1935
2667
  return NGX_OK;
1936
2668
  }
@@ -2012,7 +2744,7 @@ done:
2012
2744
  n = *src++;
2013
2745
 
2014
2746
  } else {
2015
- ngx_memcpy(dst, src, n);
2747
+ ngx_strlow(dst, src, n);
2016
2748
  dst += n;
2017
2749
  src += n;
2018
2750
 
@@ -2061,10 +2793,16 @@ ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
2061
2793
  ngx_resolver_free_locked(r, rn->u.cname);
2062
2794
  }
2063
2795
 
2064
- if (rn->naddrs > 1) {
2796
+ if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
2065
2797
  ngx_resolver_free_locked(r, rn->u.addrs);
2066
2798
  }
2067
2799
 
2800
+ #if (NGX_HAVE_INET6)
2801
+ if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
2802
+ ngx_resolver_free_locked(r, rn->u6.addrs6);
2803
+ }
2804
+ #endif
2805
+
2068
2806
  ngx_resolver_free_locked(r, rn);
2069
2807
 
2070
2808
  /* unlock alloc mutex */
@@ -2136,27 +2874,84 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
2136
2874
  }
2137
2875
 
2138
2876
 
2139
- static in_addr_t *
2140
- ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
2877
+ static ngx_addr_t *
2878
+ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2879
+ ngx_uint_t rotate)
2141
2880
  {
2142
- void *dst, *p;
2143
- ngx_uint_t j;
2881
+ ngx_addr_t *dst;
2882
+ ngx_uint_t d, i, j, n;
2883
+ u_char (*sockaddr)[NGX_SOCKADDRLEN];
2884
+ in_addr_t *addr;
2885
+ struct sockaddr_in *sin;
2886
+ #if (NGX_HAVE_INET6)
2887
+ struct in6_addr *addr6;
2888
+ struct sockaddr_in6 *sin6;
2889
+ #endif
2144
2890
 
2145
- dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
2891
+ n = rn->naddrs;
2892
+ #if (NGX_HAVE_INET6)
2893
+ n += rn->naddrs6;
2894
+ #endif
2146
2895
 
2896
+ dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
2147
2897
  if (dst == NULL) {
2148
- return dst;
2898
+ return NULL;
2149
2899
  }
2150
2900
 
2151
- j = ngx_random() % n;
2901
+ sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
2902
+ if (sockaddr == NULL) {
2903
+ ngx_resolver_free(r, dst);
2904
+ return NULL;
2905
+ }
2152
2906
 
2153
- if (j == 0) {
2154
- ngx_memcpy(dst, src, n * sizeof(in_addr_t));
2155
- return dst;
2907
+ i = 0;
2908
+ d = rotate ? ngx_random() % n : 0;
2909
+
2910
+ if (rn->naddrs) {
2911
+ j = rotate ? ngx_random() % rn->naddrs : 0;
2912
+
2913
+ addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
2914
+
2915
+ do {
2916
+ sin = (struct sockaddr_in *) sockaddr[d];
2917
+ sin->sin_family = AF_INET;
2918
+ sin->sin_addr.s_addr = addr[j++];
2919
+ dst[d].sockaddr = (struct sockaddr *) sin;
2920
+ dst[d++].socklen = sizeof(struct sockaddr_in);
2921
+
2922
+ if (d == n) {
2923
+ d = 0;
2924
+ }
2925
+
2926
+ if (j == rn->naddrs) {
2927
+ j = 0;
2928
+ }
2929
+ } while (++i < rn->naddrs);
2156
2930
  }
2157
2931
 
2158
- p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
2159
- ngx_memcpy(p, src, j * sizeof(in_addr_t));
2932
+ #if (NGX_HAVE_INET6)
2933
+ if (rn->naddrs6) {
2934
+ j = rotate ? ngx_random() % rn->naddrs6 : 0;
2935
+
2936
+ addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
2937
+
2938
+ do {
2939
+ sin6 = (struct sockaddr_in6 *) sockaddr[d];
2940
+ sin6->sin6_family = AF_INET6;
2941
+ ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
2942
+ dst[d].sockaddr = (struct sockaddr *) sin6;
2943
+ dst[d++].socklen = sizeof(struct sockaddr_in6);
2944
+
2945
+ if (d == n) {
2946
+ d = 0;
2947
+ }
2948
+
2949
+ if (j == rn->naddrs6) {
2950
+ j = 0;
2951
+ }
2952
+ } while (++i < n);
2953
+ }
2954
+ #endif
2160
2955
 
2161
2956
  return dst;
2162
2957
  }
@@ -2221,7 +3016,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
2221
3016
 
2222
3017
  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
2223
3018
 
2224
- if (s == -1) {
3019
+ if (s == (ngx_socket_t) -1) {
2225
3020
  ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
2226
3021
  ngx_socket_n " failed");
2227
3022
  return NGX_ERROR;
@@ -2242,14 +3037,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
2242
3037
  ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
2243
3038
  ngx_nonblocking_n " failed");
2244
3039
 
2245
- ngx_free_connection(c);
2246
-
2247
- if (ngx_close_socket(s) == -1) {
2248
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
2249
- ngx_close_socket_n " failed");
2250
- }
2251
-
2252
- return NGX_ERROR;
3040
+ goto failed;
2253
3041
  }
2254
3042
 
2255
3043
  rev = c->read;
@@ -2274,7 +3062,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
2274
3062
  #endif
2275
3063
 
2276
3064
  ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
2277
- "connect to %V, fd:%d #%d", &uc->server, s, c->number);
3065
+ "connect to %V, fd:%d #%uA", &uc->server, s, c->number);
2278
3066
 
2279
3067
  rc = connect(s, uc->sockaddr, uc->socklen);
2280
3068
 
@@ -2284,7 +3072,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
2284
3072
  ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
2285
3073
  "connect() failed");
2286
3074
 
2287
- return NGX_ERROR;
3075
+ goto failed;
2288
3076
  }
2289
3077
 
2290
3078
  /* UDP sockets are always ready to write */
@@ -2298,16 +3086,23 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
2298
3086
  /* eventport event type has no meaning: oneshot only */
2299
3087
 
2300
3088
  if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
2301
- return NGX_ERROR;
3089
+ goto failed;
2302
3090
  }
2303
3091
 
2304
3092
  } else {
2305
3093
  /* rtsig */
2306
3094
 
2307
3095
  if (ngx_add_conn(c) == NGX_ERROR) {
2308
- return NGX_ERROR;
3096
+ goto failed;
2309
3097
  }
2310
3098
  }
2311
3099
 
2312
3100
  return NGX_OK;
3101
+
3102
+ failed:
3103
+
3104
+ ngx_close_connection(c);
3105
+ uc->connection = NULL;
3106
+
3107
+ return NGX_ERROR;
2313
3108
  }