This file contains functions to assist the iterator module. More...
#include "config.h"
#include "iterator/iter_utils.h"
#include "iterator/iterator.h"
#include "iterator/iter_hints.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_donotq.h"
#include "iterator/iter_delegpt.h"
#include "iterator/iter_priv.h"
#include "services/cache/infra.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "util/net_help.h"
#include "util/module.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/regional.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/random.h"
#include "util/fptr_wlist.h"
#include "validator/val_anchor.h"
#include "util/rbtree.h"
#include "util/locks.h"
Defines | |
#define | SUSPICION_RECENT_EXPIRY 86400 |
time when nameserver glue is said to be 'recent' | |
#define | BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*3) |
penalty to validation failed blacklisted IPs | |
Functions | |
static void | fetch_fill (struct iter_env *ie, const char *str) |
fillup fetch policy array | |
static int | read_fetch_policy (struct iter_env *ie, const char *str) |
Read config string that represents the target fetch policy. | |
int | iter_apply_cfg (struct iter_env *iter_env, struct config_file *cfg) |
Process config options and set iterator module state. | |
static int | iter_filter_unsuitable (struct iter_env *iter_env, struct module_env *env, uint8_t *name, size_t namelen, uint16_t qtype, uint32_t now, struct delegpt_addr *a) |
filter out unsuitable targets | |
static int | iter_fill_rtt (struct iter_env *iter_env, struct module_env *env, uint8_t *name, size_t namelen, uint16_t qtype, uint32_t now, struct delegpt *dp, int *best_rtt, struct sock_list *blacklist) |
lookup RTT information, and also store fastest rtt (if any) | |
static int | iter_filter_order (struct iter_env *iter_env, struct module_env *env, uint8_t *name, size_t namelen, uint16_t qtype, uint32_t now, struct delegpt *dp, int *selected_rtt, int open_target, struct sock_list *blacklist) |
filter the addres list, putting best targets at front, returns number of best targets (or 0, no suitable targets) | |
struct delegpt_addr * | iter_server_selection (struct iter_env *iter_env, struct module_env *env, struct delegpt *dp, uint8_t *name, size_t namelen, uint16_t qtype, int *dnssec_expected, int *chase_to_rd, int open_target, struct sock_list *blacklist) |
Select a valid, nice target to send query to. | |
struct dns_msg * | dns_alloc_msg (ldns_buffer *pkt, struct msg_parse *msg, struct regional *region) |
Allocate dns_msg from parsed msg, in regional. | |
struct dns_msg * | dns_copy_msg (struct dns_msg *from, struct regional *region) |
Copy a dns_msg to this regional. | |
int | iter_dns_store (struct module_env *env, struct query_info *msgqinf, struct reply_info *msgrep, int is_referral, uint32_t leeway) |
Allocate a dns_msg with malloc/alloc structure and store in dns cache. | |
int | iter_ns_probability (struct ub_randstate *rnd, int n, int m) |
Select randomly with n/m probability. | |
int | iter_suspect_exists (struct query_info *qinfo, struct delegpt *dp, struct module_env *env) |
See if query is in-zone glue and we suspect that it exists. | |
static int | causes_cycle (struct module_qstate *qstate, uint8_t *name, size_t namelen, uint16_t t, uint16_t c) |
detect dependency cycle for query and target | |
void | iter_mark_cycle_targets (struct module_qstate *qstate, struct delegpt *dp) |
Mark targets that result in a dependency cycle as done, so they will not get selected as targets. | |
int | iter_dp_is_useless (struct query_info *qinfo, uint16_t qflags, struct delegpt *dp) |
See if delegation is useful or offers immediately no targets for further recursion. | |
int | iter_indicates_dnssec (struct module_env *env, struct delegpt *dp, struct dns_msg *msg, uint16_t dclass) |
See if delegation is expected to have DNSSEC information (RRSIGs) in its answers, or not. | |
int | iter_msg_has_dnssec (struct dns_msg *msg) |
See if a message contains DNSSEC. | |
int | iter_msg_from_zone (struct dns_msg *msg, struct delegpt *dp, enum response_type type, uint16_t dclass) |
See if a message is known to be from a certain zone. | |
static int | rrset_equal (struct ub_packed_rrset_key *k1, struct ub_packed_rrset_key *k2) |
check equality of two rrsets | |
int | reply_equal (struct reply_info *p, struct reply_info *q) |
Check if two replies are equal For fallback procedures. | |
void | iter_store_inzone_glue (struct module_env *env, struct query_info *qinfo, struct reply_info *rep) |
Store in-zone glue in seperate rrset cache entries for later last-resort lookups in case the child-side versions of this information fails. | |
int | iter_lookup_inzone_glue (struct module_env *env, struct delegpt *dp, struct regional *region, struct query_info *qinfo) |
Find in-zone glue from rrset cache again. | |
int | iter_get_next_root (struct iter_hints *hints, struct iter_forwards *fwd, uint16_t *c) |
Lookup next root-hint or root-forward entry. | |
void | iter_scrub_ds (struct dns_msg *msg, struct ub_packed_rrset_key *ns, uint8_t *z) |
Remove DS records that are inappropriate before they are cached. |
This file contains functions to assist the iterator module.
Configuration options. Forward zones.
int iter_apply_cfg | ( | struct iter_env * | iter_env, | |
struct config_file * | cfg | |||
) |
Process config options and set iterator module state.
Sets default values if no config is found.
iter_env,: | iterator module state. | |
cfg,: | config options. |
References config_file::do_ip6, iter_env::donotq, donotq_apply_cfg(), donotq_create(), iter_env::hints, hints_apply_cfg(), hints_create(), log_err(), iter_env::max_dependency_depth, iter_env::priv, priv_apply_cfg(), priv_create(), read_fetch_policy(), iter_env::supports_ipv6, iter_env::target_fetch_policy, config_file::target_fetch_policy, VERB_QUERY, and verbose().
Referenced by iter_init().
static int iter_filter_unsuitable | ( | struct iter_env * | iter_env, | |
struct module_env * | env, | |||
uint8_t * | name, | |||
size_t | namelen, | |||
uint16_t | qtype, | |||
uint32_t | now, | |||
struct delegpt_addr * | a | |||
) | [static] |
filter out unsuitable targets
iter_env,: | iterator environment with ipv6-support flag. | |
env,: | module environment with infra cache. | |
name,: | zone name | |
namelen,: | length of name | |
qtype,: | query type (host order). | |
now,: | current time | |
a,: | address in delegation point we are examining. |
When a final value is chosen that is dnsseclame ; dnsseclameness checking is turned off (so we do not discard the reply). When a final value is chosen that is recursionlame; RD bit is set on query. Because of the numbers this means recursionlame also have dnssec lameness checking turned off.
References delegpt_addr::addr, addr_is_ip6(), delegpt_addr::addrlen, delegpt_addr::bogus, iter_env::donotq, donotq_lookup(), module_env::infra_cache, infra_get_lame_rtt(), delegpt_addr::lame, log_addr(), iter_env::supports_ipv6, UNKNOWN_SERVER_NICENESS, USEFUL_SERVER_MAX_LOST, USEFUL_SERVER_TOP_TIMEOUT, VERB_ALGO, and verbose().
Referenced by iter_fill_rtt().
struct delegpt_addr* iter_server_selection | ( | struct iter_env * | iter_env, | |
struct module_env * | env, | |||
struct delegpt * | dp, | |||
uint8_t * | name, | |||
size_t | namelen, | |||
uint16_t | qtype, | |||
int * | dnssec_expected, | |||
int * | chase_to_rd, | |||
int | open_target, | |||
struct sock_list * | blacklist | |||
) | [read] |
Select a valid, nice target to send query to.
Sorting and removing unsuitable targets is combined.
iter_env,: | iterator module global state, with ip6 enabled and do-not-query-addresses. | |
env,: | environment with infra cache (lameness, rtt info). | |
dp,: | delegation point with result list. | |
name,: | zone name (for lameness check). | |
namelen,: | length of name. | |
qtype,: | query type that we want to send. | |
dnssec_expected,: | set to 0, if a known dnssec-lame server is selected these are not preferred, but are used as a last resort. | |
chase_to_rd,: | set to 1 if a known recursion lame server is selected these are not preferred, but are used as a last resort. | |
open_target,: | number of currently outstanding target queries. If we wait for these, perhaps more server addresses become available. | |
blacklist,: | the IP blacklist to use. |
References delegpt_addr::attempts, BLACKLIST_PENALTY, iter_filter_order(), log_assert, delegpt_addr::next_result, module_env::now, OUTBOUND_MSG_RETRY, delegpt::result_list, module_env::rnd, ub_random(), USEFUL_SERVER_TOP_TIMEOUT, VERB_ALGO, and verbose().
Referenced by processQueryTargets().
struct dns_msg* dns_alloc_msg | ( | ldns_buffer * | pkt, | |
struct msg_parse * | msg, | |||
struct regional * | regional | |||
) | [read] |
Allocate dns_msg from parsed msg, in regional.
pkt,: | packet. | |
msg,: | parsed message (cleaned and ready for regional allocation). | |
regional,: | regional to use for allocation. |
References log_err(), parse_create_msg(), dns_msg::qinfo, regional_alloc(), and dns_msg::rep.
Referenced by process_response().
Copy a dns_msg to this regional.
from,: | dns message, also in regional. | |
regional,: | regional to use for allocation. |
References dns_msg::qinfo, query_info::qname, query_info::qname_len, regional_alloc(), regional_alloc_init(), dns_msg::rep, and reply_info_copy().
Referenced by prime_supers(), and processClassResponse().
int iter_dns_store | ( | struct module_env * | env, | |
struct query_info * | qinf, | |||
struct reply_info * | rep, | |||
int | is_referral, | |||
uint32_t | leeway | |||
) |
Allocate a dns_msg with malloc/alloc structure and store in dns cache.
env,: | environment, with alloc structure and dns cache. | |
qinf,: | query info, the query for which answer is stored. | |
rep,: | reply in dns_msg from dns_alloc_msg for example. | |
is_referral,: | If true, then the given message to be stored is a referral. The cache implementation may use this as a hint. | |
leeway,: | prefetch TTL leeway to expire old rrsets quicker. |
References dns_cache_store().
Referenced by error_response_cache(), processFinished(), and processQueryResponse().
int iter_ns_probability | ( | struct ub_randstate * | rnd, | |
int | n, | |||
int | m | |||
) |
Select randomly with n/m probability.
For shuffle NS records for address fetching.
rnd,: | random table | |
n,: | probability. | |
m,: | divisor for probability. |
References ub_random().
Referenced by query_for_targets().
int iter_suspect_exists | ( | struct query_info * | qinfo, | |
struct delegpt * | dp, | |||
struct module_env * | env | |||
) |
See if query is in-zone glue and we suspect that it exists.
Suspicion that it exists, is if there is no A or AAAA in cache (since one of them is expected for an NS record) or the qtype is in cache but was recently expired (so we have seen this data recently).
qinfo,: | query info. | |
dp,: | delegation point we are at. | |
env,: | environment with rrset cache. |
References lruhash_entry::data, delegpt_find_ns(), dname_subdomain_c(), ub_packed_rrset_key::entry, lruhash_entry::lock, delegpt::name, module_env::now, query_info::qclass, query_info::qname, query_info::qname_len, query_info::qtype, module_env::rrset_cache, rrset_cache_lookup(), SUSPICION_RECENT_EXPIRY, packed_rrset_data::ttl, VERB_ALGO, and verbose().
Referenced by processQueryTargets().
void iter_mark_cycle_targets | ( | struct module_qstate * | qstate, | |
struct delegpt * | dp | |||
) |
Mark targets that result in a dependency cycle as done, so they will not get selected as targets.
qstate,: | query state. | |
dp,: | delegpt to mark ns in. |
References causes_cycle(), log_nametypeclass(), delegpt_ns::name, delegpt_ns::namelen, delegpt_ns::next, delegpt::nslist, query_info::qclass, module_qstate::qinfo, delegpt_ns::resolved, and VERB_QUERY.
Referenced by query_for_targets().
int iter_dp_is_useless | ( | struct query_info * | qinfo, | |
uint16_t | qflags, | |||
struct delegpt * | dp | |||
) |
See if delegation is useful or offers immediately no targets for further recursion.
qinfo,: | query name and type | |
qflags,: | query flags with RD flag | |
dp,: | delegpt to check. |
References BIT_RD, delegpt_find_ns(), dname_subdomain_c(), delegpt_ns::name, delegpt::name, delegpt_ns::next, delegpt::nslist, query_info::qname, query_info::qname_len, query_info::qtype, delegpt_ns::resolved, delegpt::result_list, and delegpt::usable_list.
Referenced by print_deleg_lookup(), and processInitRequest().
int iter_indicates_dnssec | ( | struct module_env * | env, | |
struct delegpt * | dp, | |||
struct dns_msg * | msg, | |||
uint16_t | dclass | |||
) |
See if delegation is expected to have DNSSEC information (RRSIGs) in its answers, or not.
Inspects delegation point (name), trust anchors, and delegation message (DS RRset) to determine this.
env,: | module env with trust anchors. | |
dp,: | delegation point. | |
msg,: | delegation message, with DS if a secure referral. | |
dclass,: | class of query. |
References anchor_find(), module_env::anchors, trust_anchor::lock, delegpt::name, delegpt::namelabs, delegpt::namelen, dns_msg::rep, and reply_find_rrset_section_ns().
Referenced by generate_target_query(), prime_root(), prime_stub(), processInitRequest3(), and processQueryResponse().
int iter_msg_has_dnssec | ( | struct dns_msg * | msg | ) |
See if a message contains DNSSEC.
This is examined by looking for RRSIGs. With DNSSEC a valid answer, nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records.
msg,: | message to examine. |
References reply_info::an_numrrsets, reply_info::ns_numrrsets, dns_msg::rep, and reply_info::rrsets.
Referenced by processQueryResponse().
int iter_msg_from_zone | ( | struct dns_msg * | msg, | |
struct delegpt * | dp, | |||
enum response_type | type, | |||
uint16_t | dclass | |||
) |
See if a message is known to be from a certain zone.
This looks for SOA or NS rrsets, for answers. For referrals, when one label is delegated, the zone is detected. Does not look at signatures.
msg,: | the message to inspect. | |
dp,: | delegation point with zone name to look for. | |
type,: | type of message. | |
dclass,: | class of query. |
References reply_info::an_numrrsets, packed_rrset_key::dname, dname_count_labels(), dname_strict_subdomain(), log_assert, delegpt::name, delegpt::namelabs, delegpt::namelen, reply_info::ns_numrrsets, dns_msg::rep, reply_find_rrset_section_an(), reply_find_rrset_section_ns(), RESPONSE_TYPE_ANSWER, RESPONSE_TYPE_CNAME, RESPONSE_TYPE_REFERRAL, ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, reply_info::rrsets, and packed_rrset_key::type.
Referenced by processQueryResponse().
static int rrset_equal | ( | struct ub_packed_rrset_key * | k1, | |
struct ub_packed_rrset_key * | k2 | |||
) | [static] |
check equality of two rrsets
k1,: | rrset | |
k2,: | rrset |
References packed_rrset_data::count, lruhash_entry::data, packed_rrset_key::dname, packed_rrset_key::dname_len, ub_packed_rrset_key::entry, packed_rrset_key::flags, query_dname_compare(), ub_packed_rrset_key::rk, packed_rrset_data::rr_data, packed_rrset_data::rr_len, packed_rrset_data::rr_ttl, packed_rrset_key::rrset_class, packed_rrset_data::rrsig_count, packed_rrset_data::security, packed_rrset_data::trust, packed_rrset_data::ttl, and packed_rrset_key::type.
Referenced by reply_equal().
int reply_equal | ( | struct reply_info * | p, | |
struct reply_info * | q | |||
) |
Check if two replies are equal For fallback procedures.
p,: | reply one. The reply has rrset data pointers in region. Does not check rrset-IDs | |
q,: | reply two |
References reply_info::an_numrrsets, reply_info::ar_numrrsets, reply_info::flags, reply_info::ns_numrrsets, reply_info::prefetch_ttl, reply_info::qdcount, reply_info::rrset_count, rrset_equal(), reply_info::rrsets, reply_info::security, and reply_info::ttl.
Referenced by process_response().
void iter_store_inzone_glue | ( | struct module_env * | env, | |
struct query_info * | qinfo, | |||
struct reply_info * | rep | |||
) |
Store in-zone glue in seperate rrset cache entries for later last-resort lookups in case the child-side versions of this information fails.
env,: | environment with cache, time, ... | |
qinfo,: | query info. must match the information stored to avoid Kaminsky-style trouble. | |
rep,: | reply with possibly A or AAAA content to store. |
References module_env::alloc, ub_packed_rrset_key::entry, packed_rrset_key::flags, lruhash_entry::hash, ub_packed_rrset_key::id, rrset_ref::id, rrset_ref::key, log_err(), module_env::now, packed_rrset_copy_alloc(), PACKED_RRSET_PARENT_SIDE, query_info::qclass, query_info::qname, query_info::qname_len, query_info::qtype, reply_find_rrset(), ub_packed_rrset_key::rk, module_env::rrset_cache, rrset_cache_update(), and rrset_key_hash().
Referenced by processQueryResponse().
int iter_lookup_inzone_glue | ( | struct module_env * | env, | |
struct delegpt * | dp, | |||
struct regional * | region, | |||
struct query_info * | qinfo | |||
) |
Find in-zone glue from rrset cache again.
env,: | query env with rrset cache and time. | |
dp,: | delegation point to store result in. | |
region,: | region to alloc result in. | |
qinfo,: | query into that is pertinent. |
References delegpt_add_rrset_A(), delegpt_add_rrset_AAAA(), ub_packed_rrset_key::entry, lruhash_entry::lock, module_env::now, PACKED_RRSET_PARENT_SIDE, query_info::qclass, query_info::qname, query_info::qname_len, query_info::qtype, module_env::rrset_cache, and rrset_cache_lookup().
Referenced by processTargetResponse().
int iter_get_next_root | ( | struct iter_hints * | hints, | |
struct iter_forwards * | fwd, | |||
uint16_t * | c | |||
) |
Lookup next root-hint or root-forward entry.
hints,: | the hints. | |
fwd,: | the forwards. | |
c,: | the class to start searching at. 0 means find first one. |
References forwards_next_root(), and hints_next_root().
Referenced by processCollectClass().
void iter_scrub_ds | ( | struct dns_msg * | msg, | |
struct ub_packed_rrset_key * | ns, | |||
uint8_t * | z | |||
) |
Remove DS records that are inappropriate before they are cached.
msg,: | the response to scrub. | |
ns,: | RRSET that is the NS record for the referral. if NULL, then all DS records are removed from the authority section. | |
z,: | zone name that the response is from. |
References reply_info::an_numrrsets, packed_rrset_key::dname, dname_subdomain_c(), log_nametypeclass(), reply_info::ns_numrrsets, query_dname_compare(), dns_msg::rep, ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, reply_info::rrset_count, reply_info::rrsets, packed_rrset_key::type, and VERB_ALGO.
Referenced by processQueryResponse().