val_neg.c File Reference

This file contains helper functions for the validator module. More...

#include "config.h"
#include "validator/val_neg.h"
#include "validator/val_nsec.h"
#include "validator/val_nsec3.h"
#include "validator/val_utils.h"
#include "util/data/dname.h"
#include "util/data/msgreply.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "services/cache/rrset.h"
#include "services/cache/dns.h"
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"

Macros

#define NSEC3_SHA_LEN   20
 

Functions

int val_neg_data_compare (const void *a, const void *b)
 Comparison function for rbtree val neg data elements.
 
int val_neg_zone_compare (const void *a, const void *b)
 Comparison function for rbtree val neg zone elements.
 
struct val_neg_cacheval_neg_create (struct config_file *cfg, size_t maxiter)
 Create negative cache. More...
 
size_t val_neg_get_mem (struct val_neg_cache *neg)
 see how much memory is in use by the negative cache. More...
 
static void neg_clear_datas (rbnode_type *n, void *ATTR_UNUSED(arg))
 clear datas on cache deletion
 
static void neg_clear_zones (rbnode_type *n, void *ATTR_UNUSED(arg))
 clear zones on cache deletion
 
void neg_cache_delete (struct val_neg_cache *neg)
 Destroy negative cache. More...
 
static void neg_lru_front (struct val_neg_cache *neg, struct val_neg_data *data)
 Put data element at the front of the LRU list. More...
 
static void neg_lru_remove (struct val_neg_cache *neg, struct val_neg_data *data)
 Remove data element from LRU list. More...
 
static void neg_lru_touch (struct val_neg_cache *neg, struct val_neg_data *data)
 Touch LRU for data element, put it at the start of the LRU list. More...
 
static void neg_delete_zone (struct val_neg_cache *neg, struct val_neg_zone *z)
 Delete a zone element from the negative cache. More...
 
void neg_delete_data (struct val_neg_cache *neg, struct val_neg_data *el)
 Delete a data element from the negative cache. More...
 
static void neg_make_space (struct val_neg_cache *neg, size_t need)
 Create more space in negative cache The oldest elements are deleted until enough space is present. More...
 
struct val_neg_zoneneg_find_zone (struct val_neg_cache *neg, uint8_t *nm, size_t len, uint16_t dclass)
 Find the given zone, from the SOA owner name and class Does not do locking. More...
 
static struct val_neg_dataneg_find_data (struct val_neg_zone *zone, uint8_t *nm, size_t len, int labs)
 Find the given data. More...
 
static size_t calc_data_need (struct reply_info *rep)
 Calculate space needed for the data and all its parents. More...
 
static size_t calc_zone_need (uint8_t *d, size_t len)
 Calculate space needed for zone and all its parents. More...
 
static struct val_neg_zoneneg_closest_zone_parent (struct val_neg_cache *neg, uint8_t *nm, size_t nm_len, int labs, uint16_t qclass)
 Find closest existing parent zone of the given name. More...
 
static struct val_neg_dataneg_closest_data_parent (struct val_neg_zone *zone, uint8_t *nm, size_t nm_len, int labs)
 Find closest existing parent data for the given name. More...
 
static struct val_neg_zoneneg_setup_zone_node (uint8_t *nm, size_t nm_len, int labs, uint16_t dclass)
 Create a single zone node. More...
 
static struct val_neg_zoneneg_zone_chain (uint8_t *nm, size_t nm_len, int labs, uint16_t dclass, struct val_neg_zone *parent)
 Create a linked list of parent zones, starting at longname ending on the parent (can be NULL, creates to the root). More...
 
void val_neg_zone_take_inuse (struct val_neg_zone *zone)
 take a zone into use. More...
 
struct val_neg_zoneneg_create_zone (struct val_neg_cache *neg, uint8_t *nm, size_t nm_len, uint16_t dclass)
 Create a new zone. More...
 
static struct ub_packed_rrset_keyreply_find_soa (struct reply_info *rep)
 find zone name of message, returns the SOA record
 
static int reply_has_nsec (struct reply_info *rep)
 see if the reply has NSEC records worthy of caching
 
static struct val_neg_dataneg_setup_data_node (uint8_t *nm, size_t nm_len, int labs)
 Create single node of data element. More...
 
static struct val_neg_dataneg_data_chain (uint8_t *nm, size_t nm_len, int labs, struct val_neg_data *parent)
 Create chain of data element and parents. More...
 
static void wipeout (struct val_neg_cache *neg, struct val_neg_zone *zone, struct val_neg_data *el, struct ub_packed_rrset_key *nsec)
 Remove NSEC records between start and end points. More...
 
void neg_insert_data (struct val_neg_cache *neg, struct val_neg_zone *zone, struct ub_packed_rrset_key *nsec)
 Insert data into the data tree of a zone Does not do locking. More...
 
static uint8_t * reply_nsec_signer (struct reply_info *rep, size_t *signer_len, uint16_t *dclass)
 see if the reply has signed NSEC records and return the signer
 
void val_neg_addreply (struct val_neg_cache *neg, struct reply_info *rep)
 Insert NSECs from this message into the negative cache for reference. More...
 
static int neg_closest_data (struct val_neg_zone *zone, uint8_t *qname, size_t len, int labs, struct val_neg_data **data)
 Lookup closest data record. More...
 
void val_neg_addreferral (struct val_neg_cache *neg, struct reply_info *rep, uint8_t *zone_name)
 Insert NSECs from this referral into the negative cache for reference. More...
 
static int nsec3_no_type (struct ub_packed_rrset_key *k, uint16_t t)
 Check that an NSEC3 rrset does not have a type set. More...
 
static struct ub_packed_rrset_keygrab_nsec (struct rrset_cache *rrset_cache, uint8_t *qname, size_t qname_len, uint16_t qtype, uint16_t qclass, uint32_t flags, struct regional *region, int checkbit, uint16_t checktype, time_t now)
 See if rrset exists in rrset cache. More...
 
static struct ub_packed_rrset_keyneg_find_nsec (struct val_neg_cache *neg_cache, uint8_t *qname, size_t qname_len, uint16_t qclass, struct rrset_cache *rrset_cache, time_t now, struct regional *region)
 Get best NSEC record for qname. More...
 
static struct val_neg_dataneg_find_nsec3_ce (struct val_neg_zone *zone, uint8_t *qname, size_t qname_len, int qlabs, sldns_buffer *buf, uint8_t *hashnc, size_t *nclen)
 find nsec3 closest encloser in neg cache
 
static int neg_params_ok (struct val_neg_zone *zone, struct ub_packed_rrset_key *rrset)
 check nsec3 parameters on nsec3 rrset with current zone values
 
static struct ub_packed_rrset_keyneg_nsec3_getnc (struct val_neg_zone *zone, uint8_t *hashnc, size_t nclen, struct rrset_cache *rrset_cache, struct regional *region, time_t now, uint8_t *b32, size_t maxb32)
 get next closer for nsec3 proof
 
static struct dns_msgneg_nsec3_proof_ds (struct val_neg_zone *zone, uint8_t *qname, size_t qname_len, int qlabs, sldns_buffer *buf, struct rrset_cache *rrset_cache, struct regional *region, time_t now, uint8_t *topname)
 neg cache nsec3 proof procedure
 
static int add_soa (struct rrset_cache *rrset_cache, time_t now, struct regional *region, struct dns_msg *msg, struct val_neg_zone *zone)
 Add SOA record for external responses. More...
 
struct dns_msgval_neg_getmsg (struct val_neg_cache *neg, struct query_info *qinfo, struct regional *region, struct rrset_cache *rrset_cache, sldns_buffer *buf, time_t now, int addsoa, uint8_t *topname, struct config_file *cfg)
 For the given query, try to get a reply out of the negative cache. More...
 

Detailed Description

This file contains helper functions for the validator module.

The functions help with aggressive negative caching. This creates new denials of existence, and proofs for absence of types from cached NSEC records.

Function Documentation

◆ val_neg_create()

struct val_neg_cache* val_neg_create ( struct config_file cfg,
size_t  maxiter 
)

Create negative cache.

Parameters
cfgconfig options.
maxitermax nsec3 iterations allowed.
Returns
neg cache, empty or NULL on failure.

References val_neg_cache::lock, log_err(), val_neg_cache::max, config_file::neg_cache_size, val_neg_cache::nsec3_max_iter, rbtree_init(), val_neg_cache::tree, and val_neg_zone_compare().

Referenced by neg_test(), and val_apply_cfg().

◆ val_neg_get_mem()

size_t val_neg_get_mem ( struct val_neg_cache neg)

see how much memory is in use by the negative cache.

Parameters
negnegative cache
Returns
number of bytes in use.

References val_neg_cache::lock, and val_neg_cache::use.

◆ neg_cache_delete()

void neg_cache_delete ( struct val_neg_cache neg)

Destroy negative cache.

There must no longer be any other threads.

Parameters
negnegative cache.

References val_neg_cache::lock, neg_clear_zones(), traverse_postorder(), and val_neg_cache::tree.

Referenced by neg_test(), and val_deinit().

◆ neg_lru_front()

static void neg_lru_front ( struct val_neg_cache neg,
struct val_neg_data data 
)
static

Put data element at the front of the LRU list.

Parameters
negnegative cache with LRU start and end.
datathis data is fronted.

References val_neg_cache::first, val_neg_cache::last, val_neg_data::next, and val_neg_data::prev.

Referenced by neg_insert_data(), and neg_lru_touch().

◆ neg_lru_remove()

static void neg_lru_remove ( struct val_neg_cache neg,
struct val_neg_data data 
)
static

Remove data element from LRU list.

Parameters
negnegative cache with LRU start and end.
datathis data is removed from the list.

References val_neg_cache::first, val_neg_cache::last, val_neg_data::next, and val_neg_data::prev.

Referenced by neg_delete_data(), and neg_lru_touch().

◆ neg_lru_touch()

static void neg_lru_touch ( struct val_neg_cache neg,
struct val_neg_data data 
)
static

Touch LRU for data element, put it at the start of the LRU list.

Parameters
negnegative cache with LRU start and end.
datathis data is used.

References val_neg_cache::first, neg_lru_front(), and neg_lru_remove().

Referenced by neg_insert_data().

◆ neg_delete_zone()

static void neg_delete_zone ( struct val_neg_cache neg,
struct val_neg_zone z 
)
static

Delete a zone element from the negative cache.

May delete other zone elements to keep tree coherent, or only mark the element as 'not in use'.

Parameters
negnegative cache.
zzone element to delete.

References val_neg_zone::count, val_neg_zone::in_use, val_neg_zone::len, log_assert, val_neg_zone::name, val_neg_zone::node, val_neg_zone::nsec3_salt, val_neg_zone::parent, rbtree_delete(), val_neg_cache::tree, and val_neg_cache::use.

Referenced by neg_delete_data().

◆ neg_delete_data()

void neg_delete_data ( struct val_neg_cache neg,
struct val_neg_data el 
)

Delete a data element from the negative cache.

May delete other data elements to keep tree coherent, or only mark the element as 'not in use'. Does not do locking.

Parameters
negnegative cache.
eldata element to delete.

References rbtree_type::count, val_neg_data::count, val_neg_cache::first, val_neg_data::in_use, val_neg_cache::last, val_neg_data::len, log_assert, val_neg_data::name, neg_delete_zone(), neg_lru_remove(), val_neg_data::node, val_neg_data::parent, rbtree_delete(), val_neg_zone::tree, val_neg_cache::use, and val_neg_data::zone.

Referenced by neg_make_space(), and remove_item().

◆ neg_make_space()

static void neg_make_space ( struct val_neg_cache neg,
size_t  need 
)
static

Create more space in negative cache The oldest elements are deleted until enough space is present.

Empty zones are deleted.

Parameters
negnegative cache.
needhow many bytes are needed.

References val_neg_cache::last, val_neg_cache::max, neg_delete_data(), and val_neg_cache::use.

Referenced by val_neg_addreferral(), and val_neg_addreply().

◆ neg_find_zone()

struct val_neg_zone* neg_find_zone ( struct val_neg_cache neg,
uint8_t *  nm,
size_t  len,
uint16_t  dclass 
)

Find the given zone, from the SOA owner name and class Does not do locking.

Parameters
negnegative cache
nmwhat to look for.
lenlength of nm
dclassclass to look for.
Returns
zone or NULL if not found.

References val_neg_zone::dclass, dname_count_labels(), rbnode_type::key, val_neg_zone::labs, val_neg_zone::len, val_neg_zone::name, val_neg_zone::node, rbtree_search(), and val_neg_cache::tree.

Referenced by add_item(), val_neg_addreferral(), and val_neg_addreply().

◆ neg_find_data()

static struct val_neg_data* neg_find_data ( struct val_neg_zone zone,
uint8_t *  nm,
size_t  len,
int  labs 
)
static

Find the given data.

Parameters
zonenegative zone
nmwhat to look for.
lenlength of nm
labslabels in nm
Returns
data or NULL if not found.

References rbnode_type::key, val_neg_data::labs, val_neg_data::len, val_neg_data::name, val_neg_data::node, rbtree_search(), val_neg_zone::tree, and val_neg_data::zone.

◆ calc_data_need()

static size_t calc_data_need ( struct reply_info rep)
static

Calculate space needed for the data and all its parents.

Parameters
repNSEC entries.
Returns
size.

References reply_info::an_numrrsets, val_neg_data::len, reply_info::ns_numrrsets, ub_packed_rrset_key::rk, reply_info::rrsets, and packed_rrset_key::type.

Referenced by val_neg_addreferral(), and val_neg_addreply().

◆ calc_zone_need()

static size_t calc_zone_need ( uint8_t *  d,
size_t  len 
)
static

Calculate space needed for zone and all its parents.

Parameters
dname of zone
lenlength of name
Returns
size.

References dname_is_root(), dname_remove_label(), val_neg_zone::len, and log_assert.

Referenced by val_neg_addreferral(), and val_neg_addreply().

◆ neg_closest_zone_parent()

static struct val_neg_zone* neg_closest_zone_parent ( struct val_neg_cache neg,
uint8_t *  nm,
size_t  nm_len,
int  labs,
uint16_t  qclass 
)
static

Find closest existing parent zone of the given name.

Parameters
negnegative cache.
nmname to look for
nm_lenlength of nm
labslabelcount of nm.
qclassclass.
Returns
the zone or NULL if none found.

References val_neg_zone::dclass, dname_lab_cmp(), rbnode_type::key, val_neg_zone::labs, val_neg_zone::len, val_neg_zone::name, val_neg_zone::node, val_neg_zone::parent, rbtree_find_less_equal(), and val_neg_cache::tree.

Referenced by neg_create_zone(), and neg_find_nsec().

◆ neg_closest_data_parent()

static struct val_neg_data* neg_closest_data_parent ( struct val_neg_zone zone,
uint8_t *  nm,
size_t  nm_len,
int  labs 
)
static

Find closest existing parent data for the given name.

Parameters
zoneto look in.
nmname to look for
nm_lenlength of nm
labslabelcount of nm.
Returns
the data or NULL if none found.

References dname_lab_cmp(), rbnode_type::key, val_neg_data::labs, val_neg_data::len, val_neg_data::name, val_neg_data::node, val_neg_data::parent, rbtree_find_less_equal(), val_neg_zone::tree, and val_neg_data::zone.

Referenced by neg_insert_data().

◆ neg_setup_zone_node()

static struct val_neg_zone* neg_setup_zone_node ( uint8_t *  nm,
size_t  nm_len,
int  labs,
uint16_t  dclass 
)
static

Create a single zone node.

Parameters
nmname for zone (copied)
nm_lenlength of name
labslabels in name.
dclassclass of zone, host order.
Returns
new zone or NULL on failure

References val_neg_zone::dclass, rbnode_type::key, val_neg_zone::labs, val_neg_zone::len, memdup(), val_neg_zone::name, val_neg_zone::node, rbtree_init(), val_neg_zone::tree, and val_neg_data_compare().

Referenced by neg_zone_chain().

◆ neg_zone_chain()

static struct val_neg_zone* neg_zone_chain ( uint8_t *  nm,
size_t  nm_len,
int  labs,
uint16_t  dclass,
struct val_neg_zone parent 
)
static

Create a linked list of parent zones, starting at longname ending on the parent (can be NULL, creates to the root).

Parameters
nmname for lowest in chain
nm_lenlength of name
labslabels in name.
dclassclass of zone.
parentNULL for to root, else so it fits under here.
Returns
zone; a chain of zones and their parents up to the parent. or NULL on malloc failure

References val_neg_zone::dclass, dname_remove_label(), val_neg_zone::labs, val_neg_zone::name, neg_setup_zone_node(), and val_neg_zone::parent.

Referenced by neg_create_zone().

◆ val_neg_zone_take_inuse()

void val_neg_zone_take_inuse ( struct val_neg_zone zone)

take a zone into use.

increases counts of parents. Does not do locking.

Parameters
zonezone to take into use.

References val_neg_zone::count, val_neg_zone::in_use, and val_neg_zone::parent.

Referenced by add_item(), val_neg_addreferral(), and val_neg_addreply().

◆ neg_create_zone()

struct val_neg_zone* neg_create_zone ( struct val_neg_cache neg,
uint8_t *  nm,
size_t  nm_len,
uint16_t  dclass 
)

Create a new zone.

Does not do locking.

Parameters
negnegative cache
nmwhat to look for.
nm_lenlength of name.
dclassclass of zone, host order.
Returns
zone or NULL if out of memory.

References val_neg_zone::count, val_neg_zone::dclass, dname_count_labels(), val_neg_zone::labs, val_neg_zone::len, log_assert, val_neg_zone::name, neg_closest_zone_parent(), neg_zone_chain(), val_neg_zone::node, val_neg_zone::parent, query_dname_compare(), rbtree_insert(), val_neg_cache::tree, and val_neg_cache::use.

Referenced by add_item(), val_neg_addreferral(), and val_neg_addreply().

◆ neg_setup_data_node()

static struct val_neg_data* neg_setup_data_node ( uint8_t *  nm,
size_t  nm_len,
int  labs 
)
static

Create single node of data element.

Parameters
nmname (copied)
nm_lenlength of name
labslabels in name.
Returns
element with name nm, or NULL malloc failure.

References rbnode_type::key, val_neg_data::labs, val_neg_data::len, memdup(), val_neg_data::name, and val_neg_data::node.

Referenced by neg_data_chain().

◆ neg_data_chain()

static struct val_neg_data* neg_data_chain ( uint8_t *  nm,
size_t  nm_len,
int  labs,
struct val_neg_data parent 
)
static

Create chain of data element and parents.

Parameters
nmname
nm_lenlength of name
labslabels in name.
parentup to where to make, if NULL up to root label.
Returns
lowest element with name nm, or NULL malloc failure.

References dname_remove_label(), val_neg_data::labs, val_neg_data::name, neg_setup_data_node(), val_neg_data::parent, and val_neg_data::prev.

Referenced by neg_insert_data().

◆ wipeout()

static void wipeout ( struct val_neg_cache neg,
struct val_neg_zone zone,
struct val_neg_data el,
struct ub_packed_rrset_key nsec 
)
static

Remove NSEC records between start and end points.

By walking the tree, the tree is sorted canonically.

Parameters
negnegative cache.
zonethe zone
elelement to start walking at.
nsecthe nsec record with the end point

References packed_rrset_data::count, ub_packed_rrset_key::rk, packed_rrset_data::rr_len, and packed_rrset_key::type.

◆ neg_insert_data()

◆ val_neg_addreply()

◆ neg_closest_data()

static int neg_closest_data ( struct val_neg_zone zone,
uint8_t *  qname,
size_t  len,
int  labs,
struct val_neg_data **  data 
)
static

Lookup closest data record.

For NSEC denial.

Parameters
zonezone to look in
qnamename to look for.
lenlength of name
labslabels in name
datadata element, exact or smaller or NULL
Returns
true if exact match.

References rbnode_type::key, val_neg_data::labs, val_neg_data::len, val_neg_data::name, val_neg_data::node, rbtree_find_less_equal(), val_neg_zone::tree, and val_neg_data::zone.

Referenced by neg_find_nsec(), and neg_nsec3_getnc().

◆ val_neg_addreferral()

void val_neg_addreferral ( struct val_neg_cache neg,
struct reply_info rep,
uint8_t *  zone 
)

Insert NSECs from this referral into the negative cache for reference.

Parameters
negnegative cache
repreferral reply with NS, NSECs.
zonebailiwick for the referral. Errors are ignored, means that storage is omitted.

References reply_info::an_numrrsets, calc_data_need(), calc_zone_need(), val_neg_zone::dclass, dname_subdomain_c(), LDNS_RR_TYPE_NS, val_neg_cache::lock, log_err(), log_nametypeclass(), neg_create_zone(), neg_find_zone(), neg_make_space(), reply_info::ns_numrrsets, reply_nsec_signer(), ub_packed_rrset_key::rk, reply_info::rrsets, packed_rrset_key::type, val_neg_zone_take_inuse(), and VERB_ALGO.

◆ nsec3_no_type()

static int nsec3_no_type ( struct ub_packed_rrset_key k,
uint16_t  t 
)
static

Check that an NSEC3 rrset does not have a type set.

None of the nsec3s in a hash-collision are allowed to have the type. (since we do not know which one is the nsec3 looked at, flags, ..., we ignore the cached item and let it bypass negative caching).

Parameters
kthe nsec3 rrset to check.
ttype to check
Returns
true if no RRs have the type.

References val_neg_zone::count, lruhash_entry::data, ub_packed_rrset_key::entry, and nsec3_has_type().

◆ grab_nsec()

static struct ub_packed_rrset_key* grab_nsec ( struct rrset_cache rrset_cache,
uint8_t *  qname,
size_t  qname_len,
uint16_t  qtype,
uint16_t  qclass,
uint32_t  flags,
struct regional region,
int  checkbit,
uint16_t  checktype,
time_t  now 
)
static

See if rrset exists in rrset cache.

If it does, the bit is checked, and if not expired, it is returned allocated in region.

Parameters
rrset_cacherrset cache
qnameto lookup rrset name
qname_lenlength of qname.
qtypetype of rrset to lookup, host order
qclassclass of rrset to lookup, host order
flagsflags for rrset to lookup
regionwhere to alloc result
checkbitif true, a bit in the nsec typemap is checked for absence.
checktypewhich bit to check
nowto check ttl against
Returns
rrset or NULL

References lruhash_entry::data, ub_packed_rrset_key::entry, lruhash_entry::lock, rrset_cache_lookup(), packed_rrset_data::rrsig_count, sec_status_secure, sec_status_unchecked, packed_rrset_data::security, and packed_rrset_data::ttl.

Referenced by neg_find_nsec(), and neg_nsec3_getnc().

◆ neg_find_nsec()

static struct ub_packed_rrset_key* neg_find_nsec ( struct val_neg_cache neg_cache,
uint8_t *  qname,
size_t  qname_len,
uint16_t  qclass,
struct rrset_cache rrset_cache,
time_t  now,
struct regional region 
)
static

Get best NSEC record for qname.

Might be matching, covering or totally useless.

Parameters
neg_cacheneg cache
qnameto lookup rrset name
qname_lenlength of qname.
qclassclass of rrset to lookup, host order
rrset_cacherrset cache
nowto check ttl against
regionwhere to alloc result
Returns
rrset or NULL

References dname_count_labels(), grab_nsec(), val_neg_zone::in_use, val_neg_data::in_use, val_neg_data::len, val_neg_cache::lock, val_neg_zone::name, val_neg_data::name, neg_closest_data(), neg_closest_zone_parent(), val_neg_zone::nsec3_hash, PACKED_RRSET_NSEC_AT_APEX, val_neg_zone::parent, query_dname_compare(), RBTREE_NULL, rbtree_previous(), and val_neg_data::zone.

◆ add_soa()

static int add_soa ( struct rrset_cache rrset_cache,
time_t  now,
struct regional region,
struct dns_msg msg,
struct val_neg_zone zone 
)
static

Add SOA record for external responses.

Parameters
rrset_cacheto look into.
nowcurrent time.
regionwhere to perform the allocation
msgcurrent msg with NSEC.
zoneval_neg_zone if we have one.
Returns
false on lookup or alloc failure.

References val_neg_zone::dclass, dns_msg_authadd(), ub_packed_rrset_key::entry, LDNS_RR_TYPE_SOA, val_neg_zone::len, lruhash_entry::lock, val_neg_zone::name, PACKED_RRSET_SOA_NEG, dns_msg::rep, reply_nsec_signer(), and rrset_cache_lookup().

◆ val_neg_getmsg()

struct dns_msg* val_neg_getmsg ( struct val_neg_cache neg,
struct query_info qinfo,
struct regional region,
struct rrset_cache rrset_cache,
struct sldns_buffer buf,
time_t  now,
int  addsoa,
uint8_t *  topname,
struct config_file cfg 
)

For the given query, try to get a reply out of the negative cache.

The reply still needs to be validated.

Parameters
negnegative cache.
qinfoquery
regionwhere to allocate reply.
rrset_cacherrset cache.
buftemporary buffer.
nowto check TTLs against.
addsoaif true, produce result for external consumption. if false, do not add SOA - for unbound-internal consumption.
topnamedo not look higher than this name, so that the result cannot be taken from a zone above the current trust anchor. Which could happen with multiple islands of trust. if NULL, then no trust anchor is used, but also the algorithm becomes more conservative, especially for opt-out zones, since the receiver may have a trust-anchor below the optout and thus the optout cannot be used to create a proof from the negative cache.
cfgconfig options.
Returns
a reply message if something was found. This reply may still need validation. NULL if nothing found (or out of memory).

References LDNS_MAX_DOMAINLEN.

Referenced by val_find_DS().