Deleted Added
full compact
iterator.c (275852) iterator.c (276605)
1/*
2 * iterator/iterator.c - iterative resolver DNS query response module
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 240 unchanged lines hidden (view full) ---

249 * @return: 0 for use by caller, to make notation easy, like:
250 * return error_response(..).
251 */
252static int
253error_response_cache(struct module_qstate* qstate, int id, int rcode)
254{
255 /* store in cache */
256 struct reply_info err;
1/*
2 * iterator/iterator.c - iterative resolver DNS query response module
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 240 unchanged lines hidden (view full) ---

249 * @return: 0 for use by caller, to make notation easy, like:
250 * return error_response(..).
251 */
252static int
253error_response_cache(struct module_qstate* qstate, int id, int rcode)
254{
255 /* store in cache */
256 struct reply_info err;
257 if(qstate->prefetch_leeway > NORR_TTL) {
258 verbose(VERB_ALGO, "error response for prefetch in cache");
259 /* attempt to adjust the cache entry prefetch */
260 if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
261 NORR_TTL, qstate->query_flags))
262 return error_response(qstate, id, rcode);
263 /* if that fails (not in cache), fall through to store err */
264 }
257 memset(&err, 0, sizeof(err));
258 err.flags = (uint16_t)(BIT_QR | BIT_RA);
259 FLAGS_SET_RCODE(err.flags, rcode);
260 err.qdcount = 1;
261 err.ttl = NORR_TTL;
262 err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
263 /* do not waste time trying to validate this servfail */
264 err.security = sec_status_indeterminate;
265 verbose(VERB_ALGO, "store error response in message cache");
265 memset(&err, 0, sizeof(err));
266 err.flags = (uint16_t)(BIT_QR | BIT_RA);
267 FLAGS_SET_RCODE(err.flags, rcode);
268 err.qdcount = 1;
269 err.ttl = NORR_TTL;
270 err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
271 /* do not waste time trying to validate this servfail */
272 err.security = sec_status_indeterminate;
273 verbose(VERB_ALGO, "store error response in message cache");
266 iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL);
274 iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
275 qstate->query_flags);
267 return error_response(qstate, id, rcode);
268}
269
270/** check if prepend item is duplicate item */
271static int
272prepend_is_duplicate(struct ub_packed_rrset_key** sets, size_t to,
273 struct ub_packed_rrset_key* dup)
274{

--- 219 unchanged lines hidden (view full) ---

494 struct iter_qstate* iq, enum iter_state initial_state,
495 enum iter_state finalstate, struct module_qstate** subq_ret, int v)
496{
497 struct module_qstate* subq = NULL;
498 struct iter_qstate* subiq = NULL;
499 uint16_t qflags = 0; /* OPCODE QUERY, no flags */
500 struct query_info qinf;
501 int prime = (finalstate == PRIME_RESP_STATE)?1:0;
276 return error_response(qstate, id, rcode);
277}
278
279/** check if prepend item is duplicate item */
280static int
281prepend_is_duplicate(struct ub_packed_rrset_key** sets, size_t to,
282 struct ub_packed_rrset_key* dup)
283{

--- 219 unchanged lines hidden (view full) ---

503 struct iter_qstate* iq, enum iter_state initial_state,
504 enum iter_state finalstate, struct module_qstate** subq_ret, int v)
505{
506 struct module_qstate* subq = NULL;
507 struct iter_qstate* subiq = NULL;
508 uint16_t qflags = 0; /* OPCODE QUERY, no flags */
509 struct query_info qinf;
510 int prime = (finalstate == PRIME_RESP_STATE)?1:0;
511 int valrec = 0;
502 qinf.qname = qname;
503 qinf.qname_len = qnamelen;
504 qinf.qtype = qtype;
505 qinf.qclass = qclass;
506
507 /* RD should be set only when sending the query back through the INIT
508 * state. */
509 if(initial_state == INIT_REQUEST_STATE)
510 qflags |= BIT_RD;
511 /* We set the CD flag so we can send this through the "head" of
512 * the resolution chain, which might have a validator. We are
513 * uninterested in validating things not on the direct resolution
514 * path. */
512 qinf.qname = qname;
513 qinf.qname_len = qnamelen;
514 qinf.qtype = qtype;
515 qinf.qclass = qclass;
516
517 /* RD should be set only when sending the query back through the INIT
518 * state. */
519 if(initial_state == INIT_REQUEST_STATE)
520 qflags |= BIT_RD;
521 /* We set the CD flag so we can send this through the "head" of
522 * the resolution chain, which might have a validator. We are
523 * uninterested in validating things not on the direct resolution
524 * path. */
515 if(!v)
525 if(!v) {
516 qflags |= BIT_CD;
526 qflags |= BIT_CD;
527 valrec = 1;
528 }
517
518 /* attach subquery, lookup existing or make a new one */
519 fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
529
530 /* attach subquery, lookup existing or make a new one */
531 fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
520 if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, &subq)) {
532 if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec,
533 &subq)) {
521 return 0;
522 }
523 *subq_ret = subq;
524 if(subq) {
525 /* initialise the new subquery */
526 subq->curmod = id;
527 subq->ext_state[id] = module_state_initial;
528 subq->minfo[id] = regional_alloc(subq->region,

--- 421 unchanged lines hidden (view full) ---

950 if(qstate->blacklist) {
951 /* if cache, or anything else, was blacklisted then
952 * getting older results from cache is a bad idea, no cache */
953 verbose(VERB_ALGO, "cache blacklisted, going to the network");
954 msg = NULL;
955 } else {
956 msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
957 iq->qchase.qname_len, iq->qchase.qtype,
534 return 0;
535 }
536 *subq_ret = subq;
537 if(subq) {
538 /* initialise the new subquery */
539 subq->curmod = id;
540 subq->ext_state[id] = module_state_initial;
541 subq->minfo[id] = regional_alloc(subq->region,

--- 421 unchanged lines hidden (view full) ---

963 if(qstate->blacklist) {
964 /* if cache, or anything else, was blacklisted then
965 * getting older results from cache is a bad idea, no cache */
966 verbose(VERB_ALGO, "cache blacklisted, going to the network");
967 msg = NULL;
968 } else {
969 msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
970 iq->qchase.qname_len, iq->qchase.qtype,
958 iq->qchase.qclass, qstate->region, qstate->env->scratch);
971 iq->qchase.qclass, qstate->query_flags,
972 qstate->region, qstate->env->scratch);
959 if(!msg && qstate->env->neg_cache) {
960 /* lookup in negative cache; may result in
961 * NOERROR/NODATA or NXDOMAIN answers that need validation */
962 msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
963 qstate->region, qstate->env->rrset_cache,
964 qstate->env->scratch_buffer,
965 *qstate->env->now, 1/*add SOA*/, NULL);
966 }

--- 916 unchanged lines hidden (view full) ---

1883 iq->dnssec_expected?"expected": "not expected",
1884 iq->dnssec_lame_query?" but lame_query anyway": "");
1885 }
1886 fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
1887 outq = (*qstate->env->send_query)(
1888 iq->qchase.qname, iq->qchase.qname_len,
1889 iq->qchase.qtype, iq->qchase.qclass,
1890 iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
973 if(!msg && qstate->env->neg_cache) {
974 /* lookup in negative cache; may result in
975 * NOERROR/NODATA or NXDOMAIN answers that need validation */
976 msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
977 qstate->region, qstate->env->rrset_cache,
978 qstate->env->scratch_buffer,
979 *qstate->env->now, 1/*add SOA*/, NULL);
980 }

--- 916 unchanged lines hidden (view full) ---

1897 iq->dnssec_expected?"expected": "not expected",
1898 iq->dnssec_lame_query?" but lame_query anyway": "");
1899 }
1900 fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
1901 outq = (*qstate->env->send_query)(
1902 iq->qchase.qname, iq->qchase.qname_len,
1903 iq->qchase.qtype, iq->qchase.qclass,
1904 iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
1891 iq->dnssec_expected, &target->addr, target->addrlen,
1892 iq->dp->name, iq->dp->namelen, qstate);
1905 iq->dnssec_expected, iq->caps_fallback, &target->addr,
1906 target->addrlen, iq->dp->name, iq->dp->namelen, qstate);
1893 if(!outq) {
1894 log_addr(VERB_DETAIL, "error sending query to auth server",
1895 &target->addr, target->addrlen);
1896 return next_state(iq, QUERYTARGETS_STATE);
1897 }
1898 outbound_list_insert(&iq->outlist, outq);
1899 iq->num_current_queries++;
1900 iq->sent_count++;

--- 119 unchanged lines hidden (view full) ---

2020 qstate->env->detach_subs));
2021 (*qstate->env->detach_subs)(qstate);
2022 iq->num_target_queries = 0;
2023 return processDSNSFind(qstate, iq, id);
2024 }
2025 iter_dns_store(qstate->env, &iq->response->qinfo,
2026 iq->response->rep, 0, qstate->prefetch_leeway,
2027 iq->dp&&iq->dp->has_parent_side_NS,
1907 if(!outq) {
1908 log_addr(VERB_DETAIL, "error sending query to auth server",
1909 &target->addr, target->addrlen);
1910 return next_state(iq, QUERYTARGETS_STATE);
1911 }
1912 outbound_list_insert(&iq->outlist, outq);
1913 iq->num_current_queries++;
1914 iq->sent_count++;

--- 119 unchanged lines hidden (view full) ---

2034 qstate->env->detach_subs));
2035 (*qstate->env->detach_subs)(qstate);
2036 iq->num_target_queries = 0;
2037 return processDSNSFind(qstate, iq, id);
2038 }
2039 iter_dns_store(qstate->env, &iq->response->qinfo,
2040 iq->response->rep, 0, qstate->prefetch_leeway,
2041 iq->dp&&iq->dp->has_parent_side_NS,
2028 qstate->region);
2042 qstate->region, qstate->query_flags);
2029 /* close down outstanding requests to be discarded */
2030 outbound_list_clear(&iq->outlist);
2031 iq->num_current_queries = 0;
2032 fptr_ok(fptr_whitelist_modenv_detach_subs(
2033 qstate->env->detach_subs));
2034 (*qstate->env->detach_subs)(qstate);
2035 iq->num_target_queries = 0;
2036 if(qstate->reply)

--- 21 unchanged lines hidden (view full) ---

2058 || reply_find_rrset_section_an(iq->response->rep,
2059 iq->qchase.qname, iq->qchase.qname_len,
2060 LDNS_RR_TYPE_NS, iq->qchase.qclass)
2061 )
2062 )) {
2063 /* Store the referral under the current query */
2064 /* no prefetch-leeway, since its not the answer */
2065 iter_dns_store(qstate->env, &iq->response->qinfo,
2043 /* close down outstanding requests to be discarded */
2044 outbound_list_clear(&iq->outlist);
2045 iq->num_current_queries = 0;
2046 fptr_ok(fptr_whitelist_modenv_detach_subs(
2047 qstate->env->detach_subs));
2048 (*qstate->env->detach_subs)(qstate);
2049 iq->num_target_queries = 0;
2050 if(qstate->reply)

--- 21 unchanged lines hidden (view full) ---

2072 || reply_find_rrset_section_an(iq->response->rep,
2073 iq->qchase.qname, iq->qchase.qname_len,
2074 LDNS_RR_TYPE_NS, iq->qchase.qclass)
2075 )
2076 )) {
2077 /* Store the referral under the current query */
2078 /* no prefetch-leeway, since its not the answer */
2079 iter_dns_store(qstate->env, &iq->response->qinfo,
2066 iq->response->rep, 1, 0, 0, NULL);
2080 iq->response->rep, 1, 0, 0, NULL, 0);
2067 if(iq->store_parent_NS)
2068 iter_store_parentside_NS(qstate->env,
2069 iq->response->rep);
2070 if(qstate->env->neg_cache)
2071 val_neg_addreferral(qstate->env->neg_cache,
2072 iq->response->rep, iq->dp->name);
2073 }
2074 /* store parent-side-in-zone-glue, if directly queried for */

--- 82 unchanged lines hidden (view full) ---

2157 &sname, &snamelen))
2158 return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
2159 /* cache the CNAME response under the current query */
2160 /* NOTE : set referral=1, so that rrsets get stored but not
2161 * the partial query answer (CNAME only). */
2162 /* prefetchleeway applied because this updates answer parts */
2163 iter_dns_store(qstate->env, &iq->response->qinfo,
2164 iq->response->rep, 1, qstate->prefetch_leeway,
2081 if(iq->store_parent_NS)
2082 iter_store_parentside_NS(qstate->env,
2083 iq->response->rep);
2084 if(qstate->env->neg_cache)
2085 val_neg_addreferral(qstate->env->neg_cache,
2086 iq->response->rep, iq->dp->name);
2087 }
2088 /* store parent-side-in-zone-glue, if directly queried for */

--- 82 unchanged lines hidden (view full) ---

2171 &sname, &snamelen))
2172 return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
2173 /* cache the CNAME response under the current query */
2174 /* NOTE : set referral=1, so that rrsets get stored but not
2175 * the partial query answer (CNAME only). */
2176 /* prefetchleeway applied because this updates answer parts */
2177 iter_dns_store(qstate->env, &iq->response->qinfo,
2178 iq->response->rep, 1, qstate->prefetch_leeway,
2165 iq->dp&&iq->dp->has_parent_side_NS, NULL);
2179 iq->dp&&iq->dp->has_parent_side_NS, NULL,
2180 qstate->query_flags);
2166 /* set the current request's qname to the new value. */
2167 iq->qchase.qname = sname;
2168 iq->qchase.qname_len = snamelen;
2169 /* Clear the query state, since this is a query restart. */
2170 iq->deleg_msg = NULL;
2171 iq->dp = NULL;
2172 iq->dsns_point = NULL;
2173 /* Note the query restart. */

--- 64 unchanged lines hidden (view full) ---

2238
2239 /* LAME, THROWAWAY and "unknown" all end up here.
2240 * Recycle to the QUERYTARGETS state to hopefully try a
2241 * different target. */
2242 return next_state(iq, QUERYTARGETS_STATE);
2243}
2244
2245/**
2181 /* set the current request's qname to the new value. */
2182 iq->qchase.qname = sname;
2183 iq->qchase.qname_len = snamelen;
2184 /* Clear the query state, since this is a query restart. */
2185 iq->deleg_msg = NULL;
2186 iq->dp = NULL;
2187 iq->dsns_point = NULL;
2188 /* Note the query restart. */

--- 64 unchanged lines hidden (view full) ---

2253
2254 /* LAME, THROWAWAY and "unknown" all end up here.
2255 * Recycle to the QUERYTARGETS state to hopefully try a
2256 * different target. */
2257 return next_state(iq, QUERYTARGETS_STATE);
2258}
2259
2260/**
2246 * Return priming query results to interestes super querystates.
2261 * Return priming query results to interested super querystates.
2247 *
2248 * Sets the delegation point and delegation message (not nonRD queries).
2249 * This is a callback from walk_supers.
2250 *
2251 * @param qstate: priming query state that finished.
2252 * @param id: module id.
2253 * @param forq: the qstate for which priming has been done.
2254 */

--- 414 unchanged lines hidden (view full) ---

2669 iq->response->rep->security = sec_status_unchecked;
2670 /* store message with the finished prepended items,
2671 * but only if we did recursion. The nonrecursion referral
2672 * from cache does not need to be stored in the msg cache. */
2673 if(qstate->query_flags&BIT_RD) {
2674 iter_dns_store(qstate->env, &qstate->qinfo,
2675 iq->response->rep, 0, qstate->prefetch_leeway,
2676 iq->dp&&iq->dp->has_parent_side_NS,
2262 *
2263 * Sets the delegation point and delegation message (not nonRD queries).
2264 * This is a callback from walk_supers.
2265 *
2266 * @param qstate: priming query state that finished.
2267 * @param id: module id.
2268 * @param forq: the qstate for which priming has been done.
2269 */

--- 414 unchanged lines hidden (view full) ---

2684 iq->response->rep->security = sec_status_unchecked;
2685 /* store message with the finished prepended items,
2686 * but only if we did recursion. The nonrecursion referral
2687 * from cache does not need to be stored in the msg cache. */
2688 if(qstate->query_flags&BIT_RD) {
2689 iter_dns_store(qstate->env, &qstate->qinfo,
2690 iq->response->rep, 0, qstate->prefetch_leeway,
2691 iq->dp&&iq->dp->has_parent_side_NS,
2677 qstate->region);
2692 qstate->region, qstate->query_flags);
2678 }
2679 }
2680 qstate->return_rcode = LDNS_RCODE_NOERROR;
2681 qstate->return_msg = iq->response;
2682 return 0;
2683}
2684
2685/*

--- 108 unchanged lines hidden (view full) ---

2794 struct msg_parse* prs;
2795 struct edns_data edns;
2796 sldns_buffer* pkt;
2797
2798 verbose(VERB_ALGO, "process_response: new external response event");
2799 iq->response = NULL;
2800 iq->state = QUERY_RESP_STATE;
2801 if(event == module_event_noreply || event == module_event_error) {
2693 }
2694 }
2695 qstate->return_rcode = LDNS_RCODE_NOERROR;
2696 qstate->return_msg = iq->response;
2697 return 0;
2698}
2699
2700/*

--- 108 unchanged lines hidden (view full) ---

2809 struct msg_parse* prs;
2810 struct edns_data edns;
2811 sldns_buffer* pkt;
2812
2813 verbose(VERB_ALGO, "process_response: new external response event");
2814 iq->response = NULL;
2815 iq->state = QUERY_RESP_STATE;
2816 if(event == module_event_noreply || event == module_event_error) {
2817 if(event == module_event_noreply && iq->sent_count >= 3 &&
2818 qstate->env->cfg->use_caps_bits_for_id &&
2819 !iq->caps_fallback) {
2820 /* start fallback */
2821 iq->caps_fallback = 1;
2822 iq->caps_server = 0;
2823 iq->caps_reply = NULL;
2824 iq->state = QUERYTARGETS_STATE;
2825 iq->num_current_queries--;
2826 /* need fresh attempts for the 0x20 fallback, if
2827 * that was the cause for the failure */
2828 iter_dec_attempts(iq->dp, 3);
2829 verbose(VERB_DETAIL, "Capsforid: timeouts, starting fallback");
2830 goto handle_it;
2831 }
2802 goto handle_it;
2803 }
2804 if( (event != module_event_reply && event != module_event_capsfail)
2805 || !qstate->reply) {
2806 log_err("Bad event combined with response");
2807 outbound_list_remove(&iq->outlist, outbound);
2808 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
2809 return;

--- 32 unchanged lines hidden (view full) ---

2842 goto handle_it;
2843 log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
2844 log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
2845 &qstate->reply->addr, qstate->reply->addrlen);
2846 if(verbosity >= VERB_ALGO)
2847 log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
2848 iq->response->rep);
2849
2832 goto handle_it;
2833 }
2834 if( (event != module_event_reply && event != module_event_capsfail)
2835 || !qstate->reply) {
2836 log_err("Bad event combined with response");
2837 outbound_list_remove(&iq->outlist, outbound);
2838 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
2839 return;

--- 32 unchanged lines hidden (view full) ---

2872 goto handle_it;
2873 log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
2874 log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
2875 &qstate->reply->addr, qstate->reply->addrlen);
2876 if(verbosity >= VERB_ALGO)
2877 log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
2878 iq->response->rep);
2879
2850 if(event == module_event_capsfail) {
2880 if(event == module_event_capsfail || iq->caps_fallback) {
2851 if(!iq->caps_fallback) {
2852 /* start fallback */
2853 iq->caps_fallback = 1;
2854 iq->caps_server = 0;
2855 iq->caps_reply = iq->response->rep;
2856 iq->state = QUERYTARGETS_STATE;
2857 iq->num_current_queries--;
2858 verbose(VERB_DETAIL, "Capsforid: starting fallback");
2859 goto handle_it;
2860 } else {
2861 /* check if reply is the same, otherwise, fail */
2881 if(!iq->caps_fallback) {
2882 /* start fallback */
2883 iq->caps_fallback = 1;
2884 iq->caps_server = 0;
2885 iq->caps_reply = iq->response->rep;
2886 iq->state = QUERYTARGETS_STATE;
2887 iq->num_current_queries--;
2888 verbose(VERB_DETAIL, "Capsforid: starting fallback");
2889 goto handle_it;
2890 } else {
2891 /* check if reply is the same, otherwise, fail */
2862 if(!reply_equal(iq->response->rep, iq->caps_reply,
2892 if(!iq->caps_reply) {
2893 iq->caps_reply = iq->response->rep;
2894 iq->caps_server = -1; /*become zero at ++,
2895 so that we start the full set of trials */
2896 } else if(!reply_equal(iq->response->rep, iq->caps_reply,
2863 qstate->env->scratch)) {
2864 verbose(VERB_DETAIL, "Capsforid fallback: "
2865 "getting different replies, failed");
2866 outbound_list_remove(&iq->outlist, outbound);
2867 (void)error_response(qstate, id,
2868 LDNS_RCODE_SERVFAIL);
2869 return;
2870 }

--- 143 unchanged lines hidden ---
2897 qstate->env->scratch)) {
2898 verbose(VERB_DETAIL, "Capsforid fallback: "
2899 "getting different replies, failed");
2900 outbound_list_remove(&iq->outlist, outbound);
2901 (void)error_response(qstate, id,
2902 LDNS_RCODE_SERVFAIL);
2903 return;
2904 }

--- 143 unchanged lines hidden ---