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_cache * | val_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_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. More... | |
static struct val_neg_data * | neg_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_zone * | neg_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_data * | neg_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_zone * | neg_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_zone * | neg_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_zone * | neg_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_key * | reply_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_data * | neg_setup_data_node (uint8_t *nm, size_t nm_len, int labs) |
Create single node of data element. More... | |
static struct val_neg_data * | neg_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_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) |
See if rrset exists in rrset cache. More... | |
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) |
Get best NSEC record for qname. More... | |
static struct val_neg_data * | neg_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_key * | neg_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_msg * | neg_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_msg * | val_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... | |
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.
struct val_neg_cache* val_neg_create | ( | struct config_file * | cfg, |
size_t | maxiter | ||
) |
Create negative cache.
cfg | config options. |
maxiter | max nsec3 iterations allowed. |
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().
size_t val_neg_get_mem | ( | struct val_neg_cache * | neg | ) |
see how much memory is in use by the negative cache.
neg | negative cache |
References val_neg_cache::lock, and val_neg_cache::use.
void neg_cache_delete | ( | struct val_neg_cache * | neg | ) |
Destroy negative cache.
There must no longer be any other threads.
neg | negative cache. |
References val_neg_cache::lock, neg_clear_zones(), traverse_postorder(), and val_neg_cache::tree.
Referenced by neg_test(), and val_deinit().
|
static |
Put data element at the front of the LRU list.
neg | negative cache with LRU start and end. |
data | this 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().
|
static |
Remove data element from LRU list.
neg | negative cache with LRU start and end. |
data | this 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().
|
static |
Touch LRU for data element, put it at the start of the LRU list.
neg | negative cache with LRU start and end. |
data | this data is used. |
References val_neg_cache::first, neg_lru_front(), and neg_lru_remove().
Referenced by neg_insert_data().
|
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'.
neg | negative cache. |
z | zone 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().
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.
neg | negative cache. |
el | data 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().
|
static |
Create more space in negative cache The oldest elements are deleted until enough space is present.
Empty zones are deleted.
neg | negative cache. |
need | how 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().
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.
neg | negative cache |
nm | what to look for. |
len | length of nm |
dclass | class to look for. |
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().
|
static |
Find the given data.
zone | negative zone |
nm | what to look for. |
len | length of nm |
labs | labels in nm |
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.
|
static |
Calculate space needed for the data and all its parents.
rep | NSEC entries. |
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().
|
static |
Calculate space needed for zone and all its parents.
d | name of zone |
len | length of name |
References dname_is_root(), dname_remove_label(), val_neg_zone::len, and log_assert.
Referenced by val_neg_addreferral(), and val_neg_addreply().
|
static |
Find closest existing parent zone of the given name.
neg | negative cache. |
nm | name to look for |
nm_len | length of nm |
labs | labelcount of nm. |
qclass | class. |
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().
|
static |
Find closest existing parent data for the given name.
zone | to look in. |
nm | name to look for |
nm_len | length of nm |
labs | labelcount of nm. |
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().
|
static |
Create a single zone node.
nm | name for zone (copied) |
nm_len | length of name |
labs | labels in name. |
dclass | class of zone, host order. |
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().
|
static |
Create a linked list of parent zones, starting at longname ending on the parent (can be NULL, creates to the root).
nm | name for lowest in chain |
nm_len | length of name |
labs | labels in name. |
dclass | class of zone. |
parent | NULL for to root, else so it fits under here. |
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().
void val_neg_zone_take_inuse | ( | struct val_neg_zone * | zone | ) |
take a zone into use.
increases counts of parents. Does not do locking.
zone | zone 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().
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.
neg | negative cache |
nm | what to look for. |
nm_len | length of name. |
dclass | class of zone, host order. |
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().
|
static |
Create single node of data element.
nm | name (copied) |
nm_len | length of name |
labs | labels in name. |
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().
|
static |
Create chain of data element and parents.
nm | name |
nm_len | length of name |
labs | labels in name. |
parent | up to where to make, if NULL up to root label. |
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().
|
static |
Remove NSEC records between start and end points.
By walking the tree, the tree is sorted canonically.
neg | negative cache. |
zone | the zone |
el | element to start walking at. |
nsec | the 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.
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.
neg | negative cache |
zone | zone to insert into |
nsec | record to insert. |
References val_neg_data::count, lruhash_entry::data, packed_rrset_key::dname, dname_count_labels(), packed_rrset_key::dname_len, ub_packed_rrset_key::entry, val_neg_data::in_use, val_neg_data::labs, val_neg_data::len, log_assert, log_err(), log_nametypeclass(), val_neg_data::name, neg_closest_data_parent(), neg_data_chain(), neg_lru_front(), neg_lru_touch(), val_neg_data::node, val_neg_data::parent, query_dname_compare(), rbtree_insert(), ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, packed_rrset_data::rrsig_count, sec_status_secure, sec_status_unchecked, packed_rrset_data::security, val_neg_zone::tree, packed_rrset_key::type, val_neg_cache::use, VERB_ALGO, and val_neg_data::zone.
void val_neg_addreply | ( | struct val_neg_cache * | neg, |
struct reply_info * | rep | ||
) |
Insert NSECs from this message into the negative cache for reference.
neg | negative cache |
rep | reply with NSECs. Errors are ignored, means that storage is omitted. |
References reply_info::an_numrrsets, calc_data_need(), calc_zone_need(), packed_rrset_key::dname, packed_rrset_key::dname_len, LDNS_RR_TYPE_SOA, val_neg_cache::lock, log_err(), log_nametypeclass(), neg_create_zone(), neg_find_zone(), neg_make_space(), reply_info::ns_numrrsets, reply_find_soa(), reply_has_nsec(), reply_nsec_signer(), ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, reply_info::rrsets, packed_rrset_key::type, val_neg_zone_take_inuse(), and VERB_ALGO.
|
static |
Lookup closest data record.
For NSEC denial.
zone | zone to look in |
qname | name to look for. |
len | length of name |
labs | labels in name |
data | data element, exact or smaller or NULL |
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().
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.
neg | negative cache |
rep | referral reply with NS, NSECs. |
zone | bailiwick 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.
|
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).
k | the nsec3 rrset to check. |
t | type to check |
References val_neg_zone::count, lruhash_entry::data, ub_packed_rrset_key::entry, and nsec3_has_type().
|
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.
rrset_cache | rrset cache |
qname | to lookup rrset name |
qname_len | length of qname. |
qtype | type of rrset to lookup, host order |
qclass | class of rrset to lookup, host order |
flags | flags for rrset to lookup |
region | where to alloc result |
checkbit | if true, a bit in the nsec typemap is checked for absence. |
checktype | which bit to check |
now | to check ttl against |
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().
|
static |
Get best NSEC record for qname.
Might be matching, covering or totally useless.
neg_cache | neg cache |
qname | to lookup rrset name |
qname_len | length of qname. |
qclass | class of rrset to lookup, host order |
rrset_cache | rrset cache |
now | to check ttl against |
region | where to alloc result |
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.
|
static |
Add SOA record for external responses.
rrset_cache | to look into. |
now | current time. |
region | where to perform the allocation |
msg | current msg with NSEC. |
zone | val_neg_zone if we have one. |
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().
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.
neg | negative cache. |
qinfo | query |
region | where to allocate reply. |
rrset_cache | rrset cache. |
buf | temporary buffer. |
now | to check TTLs against. |
addsoa | if true, produce result for external consumption. if false, do not add SOA - for unbound-internal consumption. |
topname | do 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. |
cfg | config options. |
References LDNS_MAX_DOMAINLEN.
Referenced by val_find_DS().