unbound  0.1
Defines | Functions
iter_utils.c File Reference

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 "validator/val_kcache.h"
#include "validator/val_kentry.h"

Defines

#define SUSPICION_RECENT_EXPIRY   86400
 time when nameserver glue is said to be 'recent'
#define BLACKLIST_PENALTY   (USEFUL_SERVER_TOP_TIMEOUT*4)
 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_addriter_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_lame, int *chase_to_rd, int open_target, struct sock_list *blacklist)
 Select a valid, nice target to send query to.
struct dns_msgdns_alloc_msg (ldns_buffer *pkt, struct msg_parse *msg, struct regional *region)
 Allocate dns_msg from parsed msg, in regional.
struct dns_msgdns_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, struct regional *region)
 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.
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.
void iter_mark_pside_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, ldns_buffer *scratch)
 Check if two replies are equal For fallback procedures.
void iter_store_parentside_rrset (struct module_env *env, struct ub_packed_rrset_key *rrset)
 Store parent-side rrset in seperate rrset cache entries for later last-resort * lookups in case the child-side versions of this information fails.
static struct ub_packed_rrset_keyreply_get_NS_rrset (struct reply_info *rep)
 fetch NS record from reply, if any
void iter_store_parentside_NS (struct module_env *env, struct reply_info *rep)
 Store parent-side NS records from a referral message.
void iter_store_parentside_neg (struct module_env *env, struct query_info *qinfo, struct reply_info *rep)
 Store parent-side negative element, the parentside rrset does not exist, creates an rrset with empty rdata in the rrset cache with PARENTSIDE flag.
int iter_lookup_parent_NS_from_cache (struct module_env *env, struct delegpt *dp, struct regional *region, struct query_info *qinfo)
 Add parent NS record if that exists in the cache.
int iter_lookup_parent_glue_from_cache (struct module_env *env, struct delegpt *dp, struct regional *region, struct query_info *qinfo)
 Add parent-side glue if that exists in the cache.
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.
void iter_dec_attempts (struct delegpt *dp, int d)
 Remove query attempts from all available ips.
void iter_merge_retry_counts (struct delegpt *dp, struct delegpt *old)
 Add retry counts from older delegpt to newer delegpt.

Detailed Description

This file contains functions to assist the iterator module.

Configuration options. Forward zones.


Function Documentation

int iter_apply_cfg ( struct iter_env iter_env,
struct config_file cfg 
)
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

Parameters:
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.
Returns:
an integer that signals the target suitability. as follows: -1: The address should be omitted from the list. Because: o The address is bogus (DNSSEC validation failure). o Listed as donotquery o is ipv6 but no ipv6 support (in operating system). o is ipv4 but no ipv4 support (in operating system). o is lame Otherwise, an rtt in milliseconds. 0 .. USEFUL_SERVER_TOP_TIMEOUT-1 The roundtrip time timeout estimate. less than 2 minutes. Note that util/rtt.c has a MIN_TIMEOUT of 50 msec, thus values 0 .. 49 are not used, unless that is changed. USEFUL_SERVER_TOP_TIMEOUT This value exactly is given for unresponsive blacklisted. USEFUL_SERVER_TOP_TIMEOUT+1 For non-blacklisted servers: huge timeout, but has traffic. USEFUL_SERVER_TOP_TIMEOUT*1 .. parent-side lame servers get this penalty. A dispreferential server. (lame in delegpt). USEFUL_SERVER_TOP_TIMEOUT*2 .. dnsseclame servers get penalty USEFUL_SERVER_TOP_TIMEOUT*3 .. recursion lame servers get penalty UNKNOWN_SERVER_NICENESS If no information is known about the server, this is returned. 376 msec or so. +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs.

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_ipv4, iter_env::supports_ipv6, UNKNOWN_SERVER_NICENESS, 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_lame,
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.

Parameters:
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_lame,:set to 1, 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.
Returns:
best target or NULL if no target. if not null, that target is removed from the result list in the dp.

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_max(), 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.

Parameters:
pkt,:packet.
msg,:parsed message (cleaned and ready for regional allocation).
regional,:regional to use for allocation.
Returns:
newly allocated dns_msg, or NULL on memory error.

References log_err(), parse_create_msg(), dns_msg::qinfo, regional_alloc(), and dns_msg::rep.

Referenced by process_response().

struct dns_msg* dns_copy_msg ( struct dns_msg from,
struct regional regional 
) [read]

Copy a dns_msg to this regional.

Parameters:
from,:dns message, also in regional.
regional,:regional to use for allocation.
Returns:
newly allocated dns_msg, or NULL on memory error.

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,
struct regional region 
)

Allocate a dns_msg with malloc/alloc structure and store in dns cache.

Parameters:
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.
region,:to copy modified (cache is better) rrs back to.
Returns:
0 on alloc error (out of memory).

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.

Parameters:
rnd,:random table
n,:probability.
m,:divisor for probability.
Returns:
true with n/m probability.

References ub_random_max().

Referenced by query_for_targets().

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.

Parameters:
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().

void iter_mark_pside_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.

For the parent-side lookups.

Parameters:
qstate,:query state.
dp,:delegpt to mark ns in.

References causes_cycle(), delegpt_ns::done_pside4, delegpt_ns::done_pside6, log_nametypeclass(), delegpt_ns::name, delegpt_ns::namelen, delegpt_ns::next, delegpt::nslist, query_info::qclass, module_qstate::qinfo, and VERB_QUERY.

Referenced by processLastResort().

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.

Parameters:
qinfo,:query name and type
qflags,:query flags with RD flag
dp,:delegpt to check.
Returns:
true if dp is useless.

References BIT_RD, delegpt_find_ns(), dname_subdomain_c(), delegpt::name, delegpt_ns::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 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.

Parameters:
env,:module env with trust anchors.
dp,:delegation point.
msg,:delegation message, with DS if a secure referral.
dclass,:class of query.
Returns:
1 if dnssec is expected, 0 if not.

References anchor_find(), module_env::anchors, module_env::key_cache, key_cache_obtain(), key_entry_isbad(), key_entry_isgood(), key_entry_isnull(), trust_anchor::lock, delegpt::name, key_entry_key::name, delegpt::namelabs, delegpt::namelen, module_env::now, query_dname_compare(), regional_free_all(), dns_msg::rep, reply_find_rrset_section_ns(), and module_env::scratch.

Referenced by generate_parentside_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.

Parameters:
msg,:message to examine.
Returns:
true if DNSSEC information was found.

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.

Parameters:
msg,:the message to inspect.
dp,:delegation point with zone name to look for.
type,:type of message.
dclass,:class of query.
Returns:
true if message is certain to be from zone in dp->name. false if not sure (empty msg), or not from the zone.

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]
int reply_equal ( struct reply_info p,
struct reply_info q,
ldns_buffer *  buf 
)

Check if two replies are equal For fallback procedures.

Parameters:
p,:reply one. The reply has rrset data pointers in region. Does not check rrset-IDs
q,:reply two
buf,:scratch buffer.
Returns:
if one and two are equal.

References reply_info::an_numrrsets, reply_info::ar_numrrsets, reply_info::flags, reply_info::ns_numrrsets, packed_rrset_to_rr_list(), 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_parentside_rrset ( struct module_env env,
struct ub_packed_rrset_key rrset 
)

Store parent-side rrset in seperate rrset cache entries for later last-resort * lookups in case the child-side versions of this information fails.

Parameters:
env,:environment with cache, time, ...
rrset,:the rrset to store (copied). Failure to store is logged, but otherwise ignored.

References module_env::alloc, rrset_ref::id, rrset_ref::key, log_err(), module_env::now, packed_rrset_copy_alloc(), PACKED_RRSET_PARENT_SIDE, module_env::rrset_cache, rrset_cache_update(), and rrset_key_hash().

Referenced by iter_store_parentside_neg(), iter_store_parentside_NS(), and processQueryResponse().

void iter_store_parentside_NS ( struct module_env env,
struct reply_info rep 
)

Store parent-side NS records from a referral message.

Parameters:
env,:environment with cache, time, ...
rep,:response with NS rrset. Failure to store is logged, but otherwise ignored.

References iter_store_parentside_rrset(), log_rrset_key(), reply_get_NS_rrset(), and VERB_ALGO.

Referenced by processQueryResponse().

void iter_store_parentside_neg ( struct module_env env,
struct query_info qinfo,
struct reply_info rep 
)
int iter_lookup_parent_NS_from_cache ( struct module_env env,
struct delegpt dp,
struct regional region,
struct query_info qinfo 
)

Add parent NS record if that exists in the cache.

This is both new information and acts like a timeout throttle on retries.

Parameters:
env,:query env with rrset cache and time.
dp,:delegation point to store result in. Also this dp is used to see which NS name is needed.
region,:region to alloc result in.
qinfo,:pertinent information, the qclass.
Returns:
false on malloc failure. if true, the routine worked and if such cached information existed dp->has_parent_side_NS is set true.

References delegpt_rrset_add_ns(), ub_packed_rrset_key::entry, delegpt::has_parent_side_NS, lruhash_entry::lock, log_rrset_key(), delegpt::name, delegpt::namelen, module_env::now, PACKED_RRSET_PARENT_SIDE, query_info::qclass, module_env::rrset_cache, rrset_cache_lookup(), and VERB_ALGO.

Referenced by processLastResort().

int iter_lookup_parent_glue_from_cache ( struct module_env env,
struct delegpt dp,
struct regional region,
struct query_info qinfo 
)

Add parent-side glue if that exists in the cache.

This is both new information and acts like a timeout throttle on retries to fetch them.

Parameters:
env,:query env with rrset cache and time.
dp,:delegation point to store result in. Also this dp is used to see which NS name is needed.
region,:region to alloc result in.
qinfo,:pertinent information, the qclass.
Returns:
: true, it worked, no malloc failures, and new addresses (lame) have been added, giving extra options as query targets.

References delegpt_add_rrset_A(), delegpt_add_rrset_AAAA(), delegpt_count_targets(), delegpt_ns::done_pside4, delegpt_ns::done_pside6, ub_packed_rrset_key::entry, lruhash_entry::lock, log_err(), log_rrset_key(), delegpt_ns::name, delegpt_ns::namelen, delegpt_ns::next, module_env::now, delegpt::nslist, PACKED_RRSET_PARENT_SIDE, query_info::qclass, module_env::rrset_cache, rrset_cache_lookup(), and VERB_ALGO.

Referenced by processLastResort().

int iter_get_next_root ( struct iter_hints hints,
struct iter_forwards fwd,
uint16_t *  c 
)

Lookup next root-hint or root-forward entry.

Parameters:
hints,:the hints.
fwd,:the forwards.
c,:the class to start searching at. 0 means find first one.
Returns:
false if no classes found, true if found and returned in c.

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.

Parameters:
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().

void iter_dec_attempts ( struct delegpt dp,
int  d 
)

Remove query attempts from all available ips.

For 0x20.

Parameters:
dp,:delegpt.
d,:decrease.

References delegpt_addr::attempts, delegpt_addr::next_result, delegpt_addr::next_target, OUTBOUND_MSG_RETRY, delegpt::result_list, and delegpt::target_list.

Referenced by processQueryTargets().

void iter_merge_retry_counts ( struct delegpt dp,
struct delegpt old 
)

Add retry counts from older delegpt to newer delegpt.

Does not waste time on timeout'd (or other failing) addresses.

Parameters:
dp,:new delegationpoint.
old,:old delegationpoint.

References delegpt_addr::addr, delegpt_addr::addrlen, delegpt_addr::attempts, delegpt_find_addr(), log_addr(), delegpt_addr::next_target, delegpt_addr::next_usable, OUTBOUND_MSG_RETRY, delegpt::target_list, delegpt::usable_list, and VERB_ALGO.

Referenced by processQueryResponse().