comparison src/core/ngx_resolver.c @ 6371:33c4d319f08f

Resolver: improved PTR response processing. The previous code only parsed the first answer, without checking its type, and required a compressed RR name. The new code checks the RR type, supports responses with multiple answers, and doesn't require the RR name to be compressed. This has a side effect in limited support of CNAME. If a response includes both CNAME and PTR RRs, like when recursion is enabled on the server, PTR RR is handled. Full CNAME support in PTR response is not implemented in this change.
author Ruslan Ermilov <ru@nginx.com>
date Thu, 17 Dec 2015 17:21:16 +0300
parents 8c8739bdd3f1
children a6a5bacf6b74
comparison
equal deleted inserted replaced
6370:8c8739bdd3f1 6371:33c4d319f08f
2399 u_char text[NGX_SOCKADDR_STRLEN]; 2399 u_char text[NGX_SOCKADDR_STRLEN];
2400 in_addr_t addr; 2400 in_addr_t addr;
2401 int32_t ttl; 2401 int32_t ttl;
2402 ngx_int_t octet; 2402 ngx_int_t octet;
2403 ngx_str_t name; 2403 ngx_str_t name;
2404 ngx_uint_t i, mask, qident, class; 2404 ngx_uint_t mask, type, class, qident, a, i, start;
2405 ngx_queue_t *expire_queue; 2405 ngx_queue_t *expire_queue;
2406 ngx_rbtree_t *tree; 2406 ngx_rbtree_t *tree;
2407 ngx_resolver_an_t *an; 2407 ngx_resolver_an_t *an;
2408 ngx_resolver_ctx_t *ctx, *next; 2408 ngx_resolver_ctx_t *ctx, *next;
2409 ngx_resolver_node_t *rn; 2409 ngx_resolver_node_t *rn;
2552 return; 2552 return;
2553 } 2553 }
2554 2554
2555 i += sizeof(ngx_resolver_qs_t); 2555 i += sizeof(ngx_resolver_qs_t);
2556 2556
2557 if (i + 2 + sizeof(ngx_resolver_an_t) >= n) { 2557 for (a = 0; a < nan; a++) {
2558
2559 start = i;
2560
2561 while (i < n) {
2562
2563 if (buf[i] & 0xc0) {
2564 i += 2;
2565 goto found;
2566 }
2567
2568 if (buf[i] == 0) {
2569 i++;
2570 goto test_length;
2571 }
2572
2573 i += 1 + buf[i];
2574 }
2575
2558 goto short_response; 2576 goto short_response;
2559 } 2577
2560 2578 test_length:
2561 /* compression pointer to *.arpa */ 2579
2562 2580 if (i - start < 2) {
2563 if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) { 2581 err = "invalid name in DNS response";
2564 err = "invalid in-addr.arpa or ip6.arpa name in DNS response"; 2582 goto invalid;
2565 goto invalid; 2583 }
2566 } 2584
2567 2585 found:
2568 an = (ngx_resolver_an_t *) &buf[i + 2]; 2586
2569 2587 if (i + sizeof(ngx_resolver_an_t) >= n) {
2570 class = (an->class_hi << 8) + an->class_lo; 2588 goto short_response;
2571 len = (an->len_hi << 8) + an->len_lo; 2589 }
2572 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) 2590
2573 + (an->ttl[2] << 8) + (an->ttl[3]); 2591 an = (ngx_resolver_an_t *) &buf[i];
2574 2592
2575 if (class != 1) { 2593 type = (an->type_hi << 8) + an->type_lo;
2576 ngx_log_error(r->log_level, r->log, 0, 2594 class = (an->class_hi << 8) + an->class_lo;
2577 "unexpected RR class %ui", class); 2595 len = (an->len_hi << 8) + an->len_lo;
2578 goto failed; 2596 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2579 } 2597 + (an->ttl[2] << 8) + (an->ttl[3]);
2580 2598
2581 if (ttl < 0) { 2599 if (class != 1) {
2582 ttl = 0; 2600 ngx_log_error(r->log_level, r->log, 0,
2583 } 2601 "unexpected RR class %ui", class);
2584 2602 goto failed;
2585 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, 2603 }
2586 "resolver qt:%ui cl:%ui len:%uz", 2604
2587 (an->type_hi << 8) + an->type_lo, 2605 if (ttl < 0) {
2588 class, len); 2606 ttl = 0;
2589 2607 }
2590 i += 2 + sizeof(ngx_resolver_an_t); 2608
2591 2609 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2592 if (i + len > n) { 2610 "resolver qt:%ui cl:%ui len:%uz",
2593 goto short_response; 2611 type, class, len);
2594 } 2612
2613 i += sizeof(ngx_resolver_an_t);
2614
2615 switch (type) {
2616
2617 case NGX_RESOLVE_PTR:
2618
2619 goto ptr;
2620
2621 case NGX_RESOLVE_CNAME:
2622
2623 break;
2624
2625 default:
2626
2627 ngx_log_error(r->log_level, r->log, 0,
2628 "unexpected RR type %ui", type);
2629 }
2630
2631 i += len;
2632 }
2633
2634 /* unlock addr mutex */
2635
2636 ngx_log_error(r->log_level, r->log, 0,
2637 "no PTR type in DNS response");
2638 return;
2639
2640 ptr:
2595 2641
2596 if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) { 2642 if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
2597 goto failed; 2643 goto failed;
2598 } 2644 }
2599 2645