13 #define NGX_RESOLVER_UDP_SIZE 4096
54 static void ngx_resolver_cleanup(
void *data);
66 static void ngx_resolver_resend_handler(
ngx_event_t *ev);
69 static void ngx_resolver_read_response(
ngx_event_t *rev);
70 static void ngx_resolver_process_response(
ngx_resolver_t *r, u_char *buf,
72 static void ngx_resolver_process_a(
ngx_resolver_t *r, u_char *buf,
size_t n,
74 static void ngx_resolver_process_ptr(
ngx_resolver_t *r, u_char *buf,
size_t n,
83 u_char *buf, u_char *src, u_char *last);
84 static void ngx_resolver_timeout_handler(
ngx_event_t *ev);
90 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,
93 static u_char *ngx_resolver_log_error(
ngx_log_t *log, u_char *buf,
size_t len);
111 cln->
handler = ngx_resolver_cleanup;
121 if (r->
event == NULL) {
126 ngx_resolver_rbtree_insert_value);
158 for (i = 0; i < n; i++) {
159 if (
ngx_strncmp(names[i].data,
"valid=", 6) == 0) {
167 "invalid parameter: %V", &names[i]);
182 "%s in resolver \"%V\"",
196 for (j = 0; j < u.
naddrs; j++) {
208 ngx_resolver_cleanup(
void *data)
231 if (uc[i].connection) {
253 for (ctx = rn->
waiting; ctx; ctx = next) {
257 ngx_resolver_free(r, ctx->
event);
260 ngx_resolver_free(r, ctx);
265 ngx_resolver_free_node(r, rn);
314 "resolve: \"%V\"", &ctx->
name);
323 rc = ngx_resolve_name_locked(r, ctx);
338 ngx_resolver_free(r, ctx->
event);
341 ngx_resolver_free(r, ctx);
358 "resolve name done: %i", ctx->
state);
374 rn = ngx_resolver_lookup_name(r, &ctx->
name, hash);
393 "could not cancel %V resolving", &ctx->
name);
405 ngx_resolver_free_locked(r, ctx->
event);
408 ngx_resolver_free_locked(r, ctx);
420 in_addr_t addr, *addrs;
428 rn = ngx_resolver_lookup_name(r, &ctx->
name, hash);
450 addrs = ngx_resolver_rotate(r, rn->
u.
addrs, naddrs);
468 ctx->
addrs = (naddrs == 1) ? &ctx->
addr : addrs;
478 ngx_resolver_free(r, addrs);
491 return ngx_resolve_name_locked(r, ctx);
525 ngx_resolver_free_locked(r, rn->
query);
530 ngx_resolver_free_locked(r, rn->
u.
cname);
534 ngx_resolver_free_locked(r, rn->
u.
addrs);
547 if (rn->
name == NULL) {
548 ngx_resolver_free(r, rn);
559 rc = ngx_resolver_create_name_query(rn, ctx);
568 ngx_resolver_free(r, rn->
query);
569 ngx_resolver_free(r, rn->
name);
570 ngx_resolver_free(r, rn);
578 if (ngx_resolver_send_query(r, rn) !=
NGX_OK) {
582 if (ctx->
event == NULL) {
584 if (ctx->
event == NULL) {
618 ngx_resolver_free(r, rn->
query);
621 ngx_resolver_free(r, rn->
name);
623 ngx_resolver_free(r, rn);
642 rn = ngx_resolver_lookup_addr(r, ctx->
addr);
656 name = ngx_resolver_dup(r, rn->
name, rn->
nlen);
670 ngx_resolver_free(r, name);
688 ngx_resolver_free(r, rn->
query);
703 if (ngx_resolver_create_addr_query(rn, ctx) !=
NGX_OK) {
707 if (ngx_resolver_send_query(r, rn) !=
NGX_OK) {
712 if (ctx->
event == NULL) {
750 ngx_resolver_free(r, rn->
query);
753 ngx_resolver_free(r, rn);
759 ngx_resolver_free(r, ctx->
event);
762 ngx_resolver_free(r, ctx);
779 "resolve addr done: %i", ctx->
state);
789 rn = ngx_resolver_lookup_addr(r, ctx->
addr);
807 addr = ntohl(ctx->
addr);
810 "could not cancel %ud.%ud.%ud.%ud resolving",
811 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
812 (addr >> 8) & 0xff, addr & 0xff);
824 ngx_resolver_free_locked(r, ctx->
event);
827 ngx_resolver_free_locked(r, ctx);
845 for (i = 0; i < 2; i++) {
854 if (now <= rn->expire) {
859 "resolver expire \"%*s\"", (
size_t) rn->
nlen, rn->
name);
865 ngx_resolver_free_node(r, rn);
905 if ((
size_t) n != (
size_t) rn->
qlen) {
917 time_t timer, atimer, ntimer;
923 "resolver resend handler");
940 }
else if (atimer == 0) {
944 timer = (atimer < ntimer) ? atimer : ntimer;
971 if (now < rn->expire) {
976 "resolver resend \"%*s\" %p",
983 (void) ngx_resolver_send_query(r, rn);
994 ngx_resolver_free_node(r, rn);
1015 ngx_resolver_process_response(c->
data, buf, n);
1017 }
while (rev->
ready);
1022 ngx_resolver_process_response(
ngx_resolver_t *r, u_char *buf,
size_t n)
1026 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1034 goto short_response;
1045 "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
1046 ident, flags, nqs, nan,
1050 if (!(flags & 0x8000)) {
1052 "invalid DNS response %ui fl:%04Xui", ident, flags);
1056 code = flags & 0x7f;
1069 if (qident == ident) {
1071 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1086 err =
"invalid number of questions in DNS response";
1093 if (buf[i] ==
'\0') {
1101 goto short_response;
1106 err =
"zero-length domain name in DNS response";
1113 goto short_response;
1122 "resolver DNS response qt:%ui cl:%ui", qtype, qclass);
1126 "unknown query class %ui in DNS response", qclass);
1134 ngx_resolver_process_a(r, buf, n, ident, code, nan,
1141 ngx_resolver_process_ptr(r, buf, n, ident, code, nan);
1147 "unknown query type %ui in DNS response", qtype);
1155 err =
"short dns response";
1166 "DNS error (%ui: %s), query id:%ui",
1173 ngx_resolver_process_a(
ngx_resolver_t *r, u_char *buf,
size_t last,
1181 in_addr_t addr, *addrs;
1188 if (ngx_resolver_copy(r, &name, buf, &buf[12], &buf[last]) !=
NGX_OK) {
1194 hash = ngx_crc32_short(name.
data, name.
len);
1198 rn = ngx_resolver_lookup_name(r, &name, hash);
1200 if (rn == NULL || rn->
query == NULL) {
1202 "unexpected response for %V", &name);
1208 if (ident != qident) {
1210 "wrong ident %ui response for %V, expect %ui",
1211 ident, &name, qident);
1215 ngx_resolver_free(r, name.
data);
1217 if (code == 0 && nan == 0) {
1229 ngx_resolver_free_node(r, rn);
1252 for (a = 0; a < nan; a++) {
1258 if (buf[i] & 0xc0) {
1271 goto short_response;
1275 if (i - start < 2) {
1276 err =
"invalid name in dns response";
1283 goto short_response;
1290 ttl = (an->
ttl[0] << 24) + (an->
ttl[1] << 16)
1291 + (an->
ttl[2] << 8) + (an->
ttl[3]);
1301 if (i + len > last) {
1302 goto short_response;
1305 addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1306 + (buf[i + 2] << 8) + (buf[i + 3]));
1321 "unexpected qtype %ui", qtype);
1326 "resolver naddrs:%ui cname:%p ttl:%d",
1327 naddrs, cname, ttl);
1336 addrs = ngx_resolver_alloc(r, naddrs *
sizeof(in_addr_t));
1337 if (addrs == NULL) {
1344 for (a = 0; a < nan; a++) {
1348 if (buf[i] & 0xc0) {
1372 addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1373 + (buf[i + 2] << 8) + (buf[i + 3]));
1385 addrs = ngx_resolver_dup(r, rn->
u.
addrs,
1386 naddrs *
sizeof(in_addr_t));
1387 if (addrs == NULL) {
1392 rn->
naddrs = (u_short) naddrs;
1410 ctx->
addrs = (naddrs == 1) ? &ctx->
addr : addrs;
1418 ngx_resolver_free(r, addrs);
1421 ngx_resolver_free(r, rn->
query);
1430 if (ngx_resolver_copy(r, &name, buf, cname, &buf[last]) !=
NGX_OK) {
1435 "resolver cname:\"%V\"", &name);
1453 (void) ngx_resolve_name_locked(r, ctx);
1456 ngx_resolver_free(r, rn->
query);
1463 "no A or CNAME types in DNS responses, unknown query type: %ui",
1469 err =
"short dns response";
1483 ngx_resolver_free(r, name.
data);
1490 ngx_resolver_process_ptr(
ngx_resolver_t *r, u_char *buf,
size_t n,
1504 if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) !=
NGX_OK) {
1505 goto invalid_in_addr_arpa;
1511 for (mask = 0; mask < 32; mask += 8) {
1515 if (digit ==
NGX_ERROR || digit > 255) {
1516 goto invalid_in_addr_arpa;
1519 addr += digit << mask;
1523 if (
ngx_strcmp(&buf[i],
"\7in-addr\4arpa") != 0) {
1524 goto invalid_in_addr_arpa;
1529 rn = ngx_resolver_lookup_addr(r, addr);
1531 if (rn == NULL || rn->
query == NULL) {
1533 "unexpected response for %ud.%ud.%ud.%ud",
1534 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
1535 (addr >> 8) & 0xff, addr & 0xff);
1541 if (ident != qident) {
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);
1549 if (code == 0 && nan == 0) {
1561 ngx_resolver_free_node(r, rn);
1579 goto short_response;
1584 if (buf[i] != 0xc0 || buf[i + 1] != 0x0c) {
1585 err =
"invalid in-addr.arpa name in DNS response";
1592 ttl = (an->
ttl[0] << 24) + (an->
ttl[1] << 16)
1593 + (an->
ttl[2] << 8) + (an->
ttl[3]);
1600 "resolver qt:%ui cl:%ui len:%uz",
1607 goto short_response;
1610 if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) !=
NGX_OK) {
1616 if (name.
len != (
size_t) rn->
nlen
1620 ngx_resolver_free(r, rn->
name);
1623 rn->
nlen = (u_short) name.
len;
1626 name.
data = ngx_resolver_dup(r, rn->
name, name.
len);
1627 if (name.
data == NULL) {
1653 ngx_resolver_free(r, name.
data);
1657 invalid_in_addr_arpa:
1660 "invalid in-addr.arpa name in DNS response");
1665 err =
"short DNS response";
1693 while (node != sentinel) {
1695 if (hash < node->key) {
1700 if (hash > node->
key) {
1715 node = (rc < 0) ? node->
left : node->
right;
1732 while (node != sentinel) {
1734 if (addr < node->key) {
1739 if (addr > node->
key) {
1764 if (node->
key < temp->
key) {
1768 }
else if (node->
key > temp->
key) {
1781 if (*p == sentinel) {
1790 node->
left = sentinel;
1791 node->
right = sentinel;
1809 p = ngx_resolver_alloc(ctx->
resolver, len);
1814 rn->
qlen = (u_short) len;
1822 "resolve: \"%V\" %i", &ctx->
name, ident & 0xffff);
1824 query->
ident_hi = (u_char) ((ident >> 8) & 0xff);
1825 query->
ident_lo = (u_char) (ident & 0xff);
1862 if (len == 0 || len > 255) {
1873 if (len == 0 || len > 255) {
1895 +
sizeof(
".255.255.255.255.in-addr.arpa.") - 1
1898 p = ngx_resolver_alloc(ctx->
resolver, len);
1908 query->
ident_hi = (u_char) ((ident >> 8) & 0xff);
1909 query->
ident_lo = (u_char) (ident & 0xff);
1922 for (n = 0; n < 32; n += 8) {
1924 *p = (u_char) (d - &p[1]);
1929 ngx_memcpy(p,
"\7in-addr\4arpa\0\0\14\0\1", 18);
1931 rn->
qlen = (u_short)
1956 for (i = 0; i < 128; i++) {
1964 n = ((n & 0x3f) << 8) + *p;
1973 err =
"name is out of response";
1978 err =
"compression pointers loop";
1998 dst = ngx_resolver_alloc(r, len);
2009 n = ((n & 0x3f) << 8) + *src;
2053 ngx_resolver_free_locked(r, rn->
query);
2057 ngx_resolver_free_locked(r, rn->
name);
2061 ngx_resolver_free_locked(r, rn->
u.
cname);
2065 ngx_resolver_free_locked(r, rn->
u.
addrs);
2068 ngx_resolver_free_locked(r, rn);
2094 p = ngx_resolver_alloc(r, size);
2127 dst = ngx_resolver_alloc(r, size);
2145 dst = ngx_resolver_alloc(r, n *
sizeof(in_addr_t));
2158 p =
ngx_cpymem(dst, &src[j], (n - j) *
sizeof(in_addr_t));
2168 static char *errors[] = {
2176 if (err > 0 && err < 6) {
2177 return errors[err - 1];
2181 return "Operation timed out";
2184 return "Unknown error";
2189 ngx_resolver_log_error(
ngx_log_t *log, u_char *buf,
size_t len)
2269 rev->lock = &c->lock;
2270 wev->lock = &c->lock;
2271 rev->own_lock = &c->lock;
2272 wev->own_lock = &c->lock;
2277 "connect to %V, fd:%d #%d", &uc->
server, s, c->
number);
2285 "connect() failed");