infra.c File Reference

This file contains the infrastructure cache. More...

#include "config.h"
#include "sldns/rrdef.h"
#include "sldns/str2wire.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "services/cache/infra.h"
#include "util/storage/slabhash.h"
#include "util/storage/lookup3.h"
#include "util/data/dname.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "iterator/iterator.h"

Macros

#define PROBE_MAXRTO   12000 /* in msec */
 Timeout when only a single probe query per IP is allowed.
 
#define TIMEOUT_COUNT_MAX   3
 number of timeouts for a type when the domain can be blocked ; even if another type has completely rtt maxed it, the different type can do this number of packets (until those all timeout too)
 

Functions

size_t infra_sizefunc (void *k, void *ATTR_UNUSED(d))
 
int infra_compfunc (void *key1, void *key2)
 compare two addresses, returns -1, 0, or +1
 
void infra_delkeyfunc (void *k, void *ATTR_UNUSED(arg))
 
void infra_deldatafunc (void *d, void *ATTR_UNUSED(arg))
 
size_t rate_sizefunc (void *k, void *ATTR_UNUSED(d))
 
int rate_compfunc (void *key1, void *key2)
 compare two names, returns -1, 0, or +1
 
void rate_delkeyfunc (void *k, void *ATTR_UNUSED(arg))
 
void rate_deldatafunc (void *d, void *ATTR_UNUSED(arg))
 
static struct domain_limit_datadomain_limit_findcreate (struct infra_cache *infra, char *name)
 find or create element in domainlimit tree
 
static int infra_ratelimit_cfg_insert (struct infra_cache *infra, struct config_file *cfg)
 insert rate limit configuration into lookup tree
 
static int setup_domain_limits (struct infra_cache *infra, struct config_file *cfg)
 setup domain limits tree (0 on failure)
 
struct infra_cacheinfra_create (struct config_file *cfg)
 Create infra cache. More...
 
static void domain_limit_free (rbnode_type *n, void *ATTR_UNUSED(arg))
 delete domain_limit entries
 
void infra_delete (struct infra_cache *infra)
 Delete infra cache. More...
 
struct infra_cacheinfra_adjust (struct infra_cache *infra, struct config_file *cfg)
 Adjust infra cache to use updated configuration settings. More...
 
static hashvalue_type hash_addr (struct sockaddr_storage *addr, socklen_t addrlen, int use_port)
 calculate the hash value for a host key set use_port to a non-0 number to use the port in the hash calculation; 0 to ignore the port.
 
static hashvalue_type hash_infra (struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *name)
 calculate infra hash for a key
 
struct lruhash_entryinfra_lookup_nottl (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *name, size_t namelen, int wr)
 lookup version that does not check host ttl (you check it) More...
 
static void data_entry_init (struct infra_cache *infra, struct lruhash_entry *e, time_t timenow)
 init the data elements
 
static struct lruhash_entrynew_entry (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *name, size_t namelen, time_t tm)
 Create and init a new entry for a host. More...
 
int infra_host (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen, time_t timenow, int *edns_vs, uint8_t *edns_lame_known, int *to)
 Find host information to send a packet. More...
 
int infra_set_lame (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen, time_t timenow, int dnsseclame, int reclame, uint16_t qtype)
 Set a host to be lame for the given zone. More...
 
void infra_update_tcp_works (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen)
 Update information for the host, store that a TCP transaction works. More...
 
int infra_rtt_update (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen, int qtype, int roundtrip, int orig_rtt, time_t timenow)
 Update rtt information for the host. More...
 
long long infra_get_host_rto (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen, struct rtt_info *rtt, int *delay, time_t timenow, int *tA, int *tAAAA, int *tother)
 Get additional (debug) info on timing. More...
 
int infra_edns_update (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *nm, size_t nmlen, int edns_version, time_t timenow)
 Update edns information for the host. More...
 
int infra_get_lame_rtt (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *name, size_t namelen, uint16_t qtype, int *lame, int *dnsseclame, int *reclame, int *rtt, time_t timenow)
 Get Lameness information and average RTT if host is in the cache. More...
 
int infra_find_ratelimit (struct infra_cache *infra, uint8_t *name, size_t namelen)
 find the ratelimit in qps for a domain. More...
 
size_t ip_rate_sizefunc (void *k, void *ATTR_UNUSED(d))
 
int ip_rate_compfunc (void *key1, void *key2)
 
void ip_rate_delkeyfunc (void *k, void *ATTR_UNUSED(arg))
 
static struct lruhash_entryinfra_find_ratedata (struct infra_cache *infra, uint8_t *name, size_t namelen, int wr)
 find data item in array, for write access, caller unlocks
 
static struct lruhash_entryinfra_find_ip_ratedata (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, int wr)
 find data item in array for ip addresses
 
static void infra_create_ratedata (struct infra_cache *infra, uint8_t *name, size_t namelen, time_t timenow)
 create rate data item for name, number 1 in now
 
static void infra_ip_create_ratedata (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, time_t timenow)
 create rate data item for ip address
 
static int * infra_rate_find_second_or_none (void *data, time_t t, int should_add)
 Find the second and return its rate counter. More...
 
static int * infra_rate_give_second (void *data, time_t t)
 find the second and return its rate counter, if none, remove oldest to accommodate
 
static int * infra_rate_get_second (void *data, time_t t)
 find the second and return its rate counter only if it exists. More...
 
int infra_rate_max (void *data, time_t now, int backoff)
 find the maximum rate stored. More...
 
int infra_ratelimit_inc (struct infra_cache *infra, uint8_t *name, size_t namelen, time_t timenow, int backoff, struct query_info *qinfo, struct comm_reply *replylist)
 Increment the query rate counter for a delegation point. More...
 
void infra_ratelimit_dec (struct infra_cache *infra, uint8_t *name, size_t namelen, time_t timenow)
 Decrement the query rate counter for a delegation point. More...
 
int infra_ratelimit_exceeded (struct infra_cache *infra, uint8_t *name, size_t namelen, time_t timenow, int backoff)
 See if the query rate counter for a delegation point is exceeded. More...
 
size_t infra_get_mem (struct infra_cache *infra)
 Get memory used by the infra cache. More...
 
static int check_ip_ratelimit (struct sockaddr_storage *addr, socklen_t addrlen, struct sldns_buffer *buffer, int premax, int max, int has_cookie)
 
int infra_ip_ratelimit_inc (struct infra_cache *infra, struct sockaddr_storage *addr, socklen_t addrlen, time_t timenow, int has_cookie, int backoff, struct sldns_buffer *buffer)
 Update query ratelimit hash and decide whether or not a query should be dropped. More...
 

Variables

int infra_dp_ratelimit = 0
 ratelimit value for delegation point More...
 
int infra_ip_ratelimit = 0
 ratelimit value for client ip addresses, in queries per second. More...
 
int infra_ip_ratelimit_cookie = 0
 ratelimit value for client ip addresses, in queries per second. More...
 

Detailed Description

This file contains the infrastructure cache.

Function Documentation

◆ infra_create()

◆ infra_delete()

void infra_delete ( struct infra_cache infra)

◆ infra_adjust()

struct infra_cache* infra_adjust ( struct infra_cache infra,
struct config_file cfg 
)

◆ infra_lookup_nottl()

struct lruhash_entry* infra_lookup_nottl ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
int  wr 
)

◆ new_entry()

static struct lruhash_entry* new_entry ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
time_t  tm 
)
static

Create and init a new entry for a host.

Parameters
infrainfra structure with config parameters.
addrhost address.
addrlenlength of addr.
namename of zone
namelenlength of name.
tmtime now.
Returns
: the new entry or NULL on malloc failure.

References infra_key::addr, infra_key::addrlen, lruhash_entry::data, data_entry_init(), infra_key::entry, lruhash_entry::hash, hash_infra(), lruhash_entry::key, lruhash_entry::lock, memdup(), infra_key::namelen, and infra_key::zonename.

Referenced by infra_edns_update(), infra_host(), infra_rtt_update(), and infra_set_lame().

◆ infra_host()

int infra_host ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
time_t  timenow,
int *  edns_vs,
uint8_t *  edns_lame_known,
int *  to 
)

Find host information to send a packet.

Creates new entry if not found. Lameness is empty. EDNS is 0 (try with first), and rtt is returned for the first message to it. Use this to send a packet only, because it also locks out others when probing is restricted.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namedomain name of zone.
namelenlength of domain name.
timenowwhat time it is now.
edns_vsedns version it supports, is returned.
edns_lame_knownif EDNS lame (EDNS is dropped in transit) has already been probed, is returned.
totimeout to use, is returned.
Returns
: 0 on error.

References lruhash_entry::data, data_entry_init(), infra_data::edns_lame_known, infra_data::edns_version, lruhash_entry::hash, infra_cache::hosts, infra_cache::infra_keep_probing, infra_lookup_nottl(), lruhash_entry::lock, new_entry(), PROBE_MAXRTO, infra_data::probedelay, rtt_info::rto, infra_data::rtt, rtt_notimeout(), rtt_timeout(), slabhash_insert(), and USEFUL_SERVER_TOP_TIMEOUT.

Referenced by expon_timeout_backoff(), print_dp_details(), serviced_tcp_send(), and serviced_udp_send().

◆ infra_set_lame()

int infra_set_lame ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
time_t  timenow,
int  dnsseclame,
int  reclame,
uint16_t  qtype 
)

Set a host to be lame for the given zone.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namedomain name of zone apex.
namelenlength of domain name.
timenowwhat time it is now.
dnsseclameif true the host is set dnssec lame. if false, the host is marked lame (not serving the zone).
reclameif true host is a recursor not AA server. if false, dnsseclame or marked lame.
qtypethe query type for which it is lame.
Returns
: 0 on error.

References lruhash_entry::data, data_entry_init(), lruhash_entry::hash, infra_cache::hosts, infra_lookup_nottl(), infra_data::isdnsseclame, infra_data::lame_other, infra_data::lame_type_A, LDNS_RR_TYPE_A, lruhash_entry::lock, log_err(), new_entry(), infra_data::rec_lame, and slabhash_insert().

◆ infra_update_tcp_works()

void infra_update_tcp_works ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen 
)

Update information for the host, store that a TCP transaction works.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namename of zone
namelenlength of name

References lruhash_entry::data, infra_lookup_nottl(), lruhash_entry::lock, rtt_info::rto, infra_data::rtt, and RTT_MAX_TIMEOUT.

Referenced by serviced_tcp_callback().

◆ infra_rtt_update()

int infra_rtt_update ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
int  qtype,
int  roundtrip,
int  orig_rtt,
time_t  timenow 
)

Update rtt information for the host.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namezone name
namelenzone name length
qtypequery type.
roundtripestimate of roundtrip time in milliseconds or -1 for timeout.
orig_rttoriginal rtt for the query that timed out (roundtrip==-1). ignored if roundtrip != -1.
timenowwhat time it is now.
Returns
: 0 on error. new rto otherwise.

References lruhash_entry::data, data_entry_init(), lruhash_entry::hash, infra_cache::hosts, infra_lookup_nottl(), LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA, lruhash_entry::lock, new_entry(), infra_data::probedelay, rtt_info::rto, infra_data::rtt, rtt_init(), rtt_lost(), rtt_unclamped(), rtt_update(), slabhash_insert(), infra_data::timeout_A, infra_data::timeout_AAAA, TIMEOUT_COUNT_MAX, infra_data::timeout_other, and USEFUL_SERVER_TOP_TIMEOUT.

Referenced by expon_timeout_backoff().

◆ infra_get_host_rto()

long long infra_get_host_rto ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
struct rtt_info rtt,
int *  delay,
time_t  timenow,
int *  tA,
int *  tAAAA,
int *  tother 
)

Get additional (debug) info on timing.

Parameters
infrainfra cache.
addrhost address.
addrlenlength of addr.
namezone name
namelenzone name length
rttthe rtt_info is copied into here (caller alloced return struct).
delayprobe delay (if any).
timenowwhat time it is now.
tAtimeout counter on type A.
tAAAAtimeout counter on type AAAA.
tothertimeout counter on type other.
Returns
TTL the infra host element is valid for. If -1: not found in cache. TTL -2: found but expired.

References lruhash_entry::data, infra_lookup_nottl(), lruhash_entry::lock, infra_data::probedelay, infra_data::rtt, infra_data::timeout_A, infra_data::timeout_AAAA, infra_data::timeout_other, and infra_data::ttl.

Referenced by print_dp_details().

◆ infra_edns_update()

int infra_edns_update ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
int  edns_version,
time_t  timenow 
)

Update edns information for the host.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namename of zone
namelenlength of name
edns_versionthe version that it publishes. If it is known to support EDNS then no-EDNS is not stored over it.
timenowwhat time it is now.
Returns
: 0 on error.

References lruhash_entry::data, data_entry_init(), infra_data::edns_lame_known, infra_data::edns_version, lruhash_entry::hash, infra_cache::hosts, infra_lookup_nottl(), lruhash_entry::lock, new_entry(), and slabhash_insert().

◆ infra_get_lame_rtt()

int infra_get_lame_rtt ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
uint8_t *  name,
size_t  namelen,
uint16_t  qtype,
int *  lame,
int *  dnsseclame,
int *  reclame,
int *  rtt,
time_t  timenow 
)

Get Lameness information and average RTT if host is in the cache.

This information is to be used for server selection.

Parameters
infrainfrastructure cache.
addrhost address.
addrlenlength of addr.
namezone name.
namelenzone name length.
qtypethe query to be made.
lameif function returns true, this returns lameness of the zone.
dnsseclameif function returns true, this returns if the zone is dnssec-lame.
reclameif function returns true, this is if it is recursion lame.
rttif function returns true, this returns avg rtt of the server. The rtt value is unclamped and reflects recent timeouts.
timenowwhat time it is now.
Returns
if found in cache, or false if not (or TTL bad).

References lruhash_entry::data, infra_cache::infra_keep_probing, infra_lookup_nottl(), infra_data::isdnsseclame, infra_data::lame_other, infra_data::lame_type_A, LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA, lruhash_entry::lock, PROBE_MAXRTO, infra_data::probedelay, infra_data::rec_lame, rtt_info::rto, infra_data::rtt, rtt_notimeout(), rtt_unclamped(), infra_data::timeout_A, infra_data::timeout_AAAA, TIMEOUT_COUNT_MAX, infra_data::timeout_other, infra_data::ttl, and USEFUL_SERVER_TOP_TIMEOUT.

Referenced by iter_filter_unsuitable(), and print_dp_details().

◆ infra_find_ratelimit()

int infra_find_ratelimit ( struct infra_cache infra,
uint8_t *  name,
size_t  namelen 
)

◆ infra_rate_find_second_or_none()

static int* infra_rate_find_second_or_none ( void *  data,
time_t  t,
int  should_add 
)
static

Find the second and return its rate counter.

If none and should_add, remove oldest to accommodate. Else return none.

References rate_data::qps, RATE_WINDOW, and rate_data::timestamp.

Referenced by infra_rate_get_second(), and infra_rate_give_second().

◆ infra_rate_get_second()

static int* infra_rate_get_second ( void *  data,
time_t  t 
)
static

find the second and return its rate counter only if it exists.

Caller should check for NULL return value

References infra_rate_find_second_or_none().

Referenced by infra_ratelimit_dec().

◆ infra_rate_max()

int infra_rate_max ( void *  data,
time_t  now,
int  backoff 
)

find the maximum rate stored.

0 if no information. When backoff is enabled look for the maximum in the whole RATE_WINDOW.

References rate_data::qps, RATE_WINDOW, and rate_data::timestamp.

Referenced by infra_ip_ratelimit_inc(), infra_ratelimit_exceeded(), infra_ratelimit_inc(), and rate_list().

◆ infra_ratelimit_inc()

int infra_ratelimit_inc ( struct infra_cache infra,
uint8_t *  name,
size_t  namelen,
time_t  timenow,
int  backoff,
struct query_info qinfo,
struct comm_reply replylist 
)

Increment the query rate counter for a delegation point.

Parameters
infrainfra cache.
namezone name
namelenzone name length
timenowwhat time it is now.
backoffif backoff is enabled.
qinfofor logging, query name.
replylistfor logging, querier's address (if any).
Returns
1 if it could be incremented. 0 if the increment overshot the ratelimit or if in the previous second the ratelimit was exceeded. Failures like alloc failures are not returned (probably as 1).

References addr_to_str(), dname_str(), infra_create_ratedata(), infra_dp_ratelimit, infra_find_ratedata(), infra_find_ratelimit(), infra_rate_give_second(), infra_rate_max(), query_info::qclass, query_info::qname, query_info::qtype, comm_reply::remote_addr, comm_reply::remote_addrlen, sldns_wire2str_class_buf(), sldns_wire2str_type_buf(), VERB_OPS, and verbose().

Referenced by outnet_serviced_query().

◆ infra_ratelimit_dec()

void infra_ratelimit_dec ( struct infra_cache infra,
uint8_t *  name,
size_t  namelen,
time_t  timenow 
)

Decrement the query rate counter for a delegation point.

Because the reply received for the delegation point was pleasant, we do not charge this delegation point with it (i.e. it was a referral). Should call it with same second as when inc() was called.

Parameters
infrainfra cache.
namezone name
namelenzone name length
timenowwhat time it is now.

References infra_dp_ratelimit, infra_find_ratedata(), and infra_rate_get_second().

Referenced by outnet_serviced_query().

◆ infra_ratelimit_exceeded()

int infra_ratelimit_exceeded ( struct infra_cache infra,
uint8_t *  name,
size_t  namelen,
time_t  timenow,
int  backoff 
)

See if the query rate counter for a delegation point is exceeded.

So, no queries are going to be allowed.

Parameters
infrainfra cache.
namezone name
namelenzone name length
timenowwhat time it is now.
backoffif backoff is enabled.
Returns
true if exceeded.

References infra_dp_ratelimit, infra_find_ratedata(), infra_find_ratelimit(), and infra_rate_max().

◆ infra_get_mem()

size_t infra_get_mem ( struct infra_cache infra)

Get memory used by the infra cache.

Parameters
infrainfrastructure cache.
Returns
memory in use in bytes.

References infra_cache::client_ip_rates, infra_cache::domain_rates, infra_cache::hosts, and slabhash_get_mem().

◆ infra_ip_ratelimit_inc()

int infra_ip_ratelimit_inc ( struct infra_cache infra,
struct sockaddr_storage *  addr,
socklen_t  addrlen,
time_t  timenow,
int  has_cookie,
int  backoff,
struct sldns_buffer buffer 
)

Update query ratelimit hash and decide whether or not a query should be dropped.

Parameters
infrainfra cache
addrclient address
addrlenclient address length
timenowwhat time it is now.
has_cookieif the request came with a DNS Cookie.
backoffif backoff is enabled.
bufferwith query for logging.
Returns
1 if it could be incremented. 0 if the increment overshot the ratelimit and the query should be dropped.

References infra_find_ip_ratedata(), infra_ip_ratelimit, infra_rate_give_second(), and infra_rate_max().

Variable Documentation

◆ infra_dp_ratelimit

int infra_dp_ratelimit = 0

ratelimit value for delegation point

ratelimit, unless overridden by domain_limits, 0 is off

Referenced by config_set_option(), do_ratelimit_list(), infra_adjust(), infra_create(), infra_find_ratelimit(), infra_ratelimit_dec(), infra_ratelimit_exceeded(), and infra_ratelimit_inc().

◆ infra_ip_ratelimit

int infra_ip_ratelimit = 0

ratelimit value for client ip addresses, in queries per second.

ip ratelimit, 0 is off

Referenced by config_set_option(), infra_adjust(), infra_create(), and infra_ip_ratelimit_inc().

◆ infra_ip_ratelimit_cookie

int infra_ip_ratelimit_cookie = 0

ratelimit value for client ip addresses, in queries per second.

ip ratelimit for DNS Cookie clients, 0 is off

For clients with a valid DNS Cookie.

Referenced by config_set_option().