1238106Sdes/* 2238106Sdes * services/cache/infra.h - infrastructure cache, server rtt and capabilities 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains the infrastructure cache. 40238106Sdes */ 41238106Sdes 42238106Sdes#ifndef SERVICES_CACHE_INFRA_H 43238106Sdes#define SERVICES_CACHE_INFRA_H 44238106Sdes#include "util/storage/lruhash.h" 45291767Sdes#include "util/storage/dnstree.h" 46238106Sdes#include "util/rtt.h" 47238106Sdesstruct slabhash; 48238106Sdesstruct config_file; 49238106Sdes 50238106Sdes/** 51238106Sdes * Host information kept for every server, per zone. 52238106Sdes */ 53238106Sdesstruct infra_key { 54238106Sdes /** the host address. */ 55238106Sdes struct sockaddr_storage addr; 56238106Sdes /** length of addr. */ 57238106Sdes socklen_t addrlen; 58238106Sdes /** zone name in wireformat */ 59238106Sdes uint8_t* zonename; 60238106Sdes /** length of zonename */ 61238106Sdes size_t namelen; 62238106Sdes /** hash table entry, data of type infra_data. */ 63238106Sdes struct lruhash_entry entry; 64238106Sdes}; 65238106Sdes 66238106Sdes/** 67238106Sdes * Host information encompasses host capabilities and retransmission timeouts. 68238106Sdes * And lameness information (notAuthoritative, noEDNS, Recursive) 69238106Sdes */ 70238106Sdesstruct infra_data { 71238106Sdes /** TTL value for this entry. absolute time. */ 72269257Sdes time_t ttl; 73238106Sdes 74238106Sdes /** time in seconds (absolute) when probing re-commences, 0 disabled */ 75269257Sdes time_t probedelay; 76238106Sdes /** round trip times for timeout calculation */ 77238106Sdes struct rtt_info rtt; 78238106Sdes 79238106Sdes /** edns version that the host supports, -1 means no EDNS */ 80238106Sdes int edns_version; 81238106Sdes /** if the EDNS lameness is already known or not. 82238106Sdes * EDNS lame is when EDNS queries or replies are dropped, 83238106Sdes * and cause a timeout */ 84238106Sdes uint8_t edns_lame_known; 85238106Sdes 86238106Sdes /** is the host lame (does not serve the zone authoritatively), 87238106Sdes * or is the host dnssec lame (does not serve DNSSEC data) */ 88238106Sdes uint8_t isdnsseclame; 89238106Sdes /** is the host recursion lame (not AA, but RA) */ 90238106Sdes uint8_t rec_lame; 91238106Sdes /** the host is lame (not authoritative) for A records */ 92238106Sdes uint8_t lame_type_A; 93238106Sdes /** the host is lame (not authoritative) for other query types */ 94238106Sdes uint8_t lame_other; 95238106Sdes 96238106Sdes /** timeouts counter for type A */ 97238106Sdes uint8_t timeout_A; 98238106Sdes /** timeouts counter for type AAAA */ 99238106Sdes uint8_t timeout_AAAA; 100238106Sdes /** timeouts counter for others */ 101238106Sdes uint8_t timeout_other; 102238106Sdes}; 103238106Sdes 104238106Sdes/** 105238106Sdes * Infra cache 106238106Sdes */ 107238106Sdesstruct infra_cache { 108238106Sdes /** The hash table with hosts */ 109238106Sdes struct slabhash* hosts; 110238106Sdes /** TTL value for host information, in seconds */ 111238106Sdes int host_ttl; 112291767Sdes /** hash table with query rates per name: rate_key, rate_data */ 113291767Sdes struct slabhash* domain_rates; 114291767Sdes /** ratelimit settings for domains, struct domain_limit_data */ 115291767Sdes rbtree_t domain_limits; 116238106Sdes}; 117238106Sdes 118291767Sdes/** ratelimit, unless overridden by domain_limits, 0 is off */ 119291767Sdesextern int infra_dp_ratelimit; 120291767Sdes 121291767Sdes/** 122291767Sdes * ratelimit settings for domains 123291767Sdes */ 124291767Sdesstruct domain_limit_data { 125291767Sdes /** key for rbtree, must be first in struct, name of domain */ 126291767Sdes struct name_tree_node node; 127291767Sdes /** ratelimit for exact match with this name, -1 if not set */ 128291767Sdes int lim; 129291767Sdes /** ratelimit for names below this name, -1 if not set */ 130291767Sdes int below; 131291767Sdes}; 132291767Sdes 133291767Sdes/** 134291767Sdes * key for ratelimit lookups, a domain name 135291767Sdes */ 136291767Sdesstruct rate_key { 137291767Sdes /** lruhash key entry */ 138291767Sdes struct lruhash_entry entry; 139291767Sdes /** domain name in uncompressed wireformat */ 140291767Sdes uint8_t* name; 141291767Sdes /** length of name */ 142291767Sdes size_t namelen; 143291767Sdes}; 144291767Sdes 145291767Sdes/** number of seconds to track qps rate */ 146291767Sdes#define RATE_WINDOW 2 147291767Sdes 148291767Sdes/** 149291767Sdes * Data for ratelimits per domain name 150291767Sdes * It is incremented when a non-cache-lookup happens for that domain name. 151291767Sdes * The name is the delegation point we have for the name. 152291767Sdes * If a new delegation point is found (a referral reply), the previous 153291767Sdes * delegation point is decremented, and the new one is charged with the query. 154291767Sdes */ 155291767Sdesstruct rate_data { 156291767Sdes /** queries counted, for that second. 0 if not in use. */ 157291767Sdes int qps[RATE_WINDOW]; 158291767Sdes /** what the timestamp is of the qps array members, counter is 159291767Sdes * valid for that timestamp. Usually now and now-1. */ 160291767Sdes time_t timestamp[RATE_WINDOW]; 161291767Sdes}; 162291767Sdes 163238106Sdes/** infra host cache default hash lookup size */ 164238106Sdes#define INFRA_HOST_STARTSIZE 32 165238106Sdes/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */ 166238106Sdes#define INFRA_BYTES_NAME 14 167238106Sdes 168238106Sdes/** 169238106Sdes * Create infra cache. 170238106Sdes * @param cfg: config parameters or NULL for defaults. 171238106Sdes * @return: new infra cache, or NULL. 172238106Sdes */ 173238106Sdesstruct infra_cache* infra_create(struct config_file* cfg); 174238106Sdes 175238106Sdes/** 176238106Sdes * Delete infra cache. 177238106Sdes * @param infra: infrastructure cache to delete. 178238106Sdes */ 179238106Sdesvoid infra_delete(struct infra_cache* infra); 180238106Sdes 181238106Sdes/** 182238106Sdes * Adjust infra cache to use updated configuration settings. 183238106Sdes * This may clean the cache. Operates a bit like realloc. 184238106Sdes * There may be no threading or use by other threads. 185238106Sdes * @param infra: existing cache. If NULL a new infra cache is returned. 186238106Sdes * @param cfg: config options. 187238106Sdes * @return the new infra cache pointer or NULL on error. 188238106Sdes */ 189238106Sdesstruct infra_cache* infra_adjust(struct infra_cache* infra, 190238106Sdes struct config_file* cfg); 191238106Sdes 192238106Sdes/** 193238106Sdes * Plain find infra data function (used by the the other functions) 194238106Sdes * @param infra: infrastructure cache. 195238106Sdes * @param addr: host address. 196238106Sdes * @param addrlen: length of addr. 197238106Sdes * @param name: domain name of zone. 198238106Sdes * @param namelen: length of domain name. 199238106Sdes * @param wr: if true, writelock, else readlock. 200238106Sdes * @return the entry, could be expired (this is not checked) or NULL. 201238106Sdes */ 202238106Sdesstruct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra, 203238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, 204238106Sdes size_t namelen, int wr); 205238106Sdes 206238106Sdes/** 207238106Sdes * Find host information to send a packet. Creates new entry if not found. 208238106Sdes * Lameness is empty. EDNS is 0 (try with first), and rtt is returned for 209238106Sdes * the first message to it. 210238106Sdes * Use this to send a packet only, because it also locks out others when 211238106Sdes * probing is restricted. 212238106Sdes * @param infra: infrastructure cache. 213238106Sdes * @param addr: host address. 214238106Sdes * @param addrlen: length of addr. 215238106Sdes * @param name: domain name of zone. 216238106Sdes * @param namelen: length of domain name. 217238106Sdes * @param timenow: what time it is now. 218238106Sdes * @param edns_vs: edns version it supports, is returned. 219238106Sdes * @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has 220238106Sdes * already been probed, is returned. 221238106Sdes * @param to: timeout to use, is returned. 222238106Sdes * @return: 0 on error. 223238106Sdes */ 224238106Sdesint infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, 225238106Sdes socklen_t addrlen, uint8_t* name, size_t namelen, 226269257Sdes time_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to); 227238106Sdes 228238106Sdes/** 229238106Sdes * Set a host to be lame for the given zone. 230238106Sdes * @param infra: infrastructure cache. 231238106Sdes * @param addr: host address. 232238106Sdes * @param addrlen: length of addr. 233238106Sdes * @param name: domain name of zone apex. 234238106Sdes * @param namelen: length of domain name. 235238106Sdes * @param timenow: what time it is now. 236238106Sdes * @param dnsseclame: if true the host is set dnssec lame. 237238106Sdes * if false, the host is marked lame (not serving the zone). 238238106Sdes * @param reclame: if true host is a recursor not AA server. 239238106Sdes * if false, dnsseclame or marked lame. 240238106Sdes * @param qtype: the query type for which it is lame. 241238106Sdes * @return: 0 on error. 242238106Sdes */ 243238106Sdesint infra_set_lame(struct infra_cache* infra, 244238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, 245269257Sdes uint8_t* name, size_t namelen, time_t timenow, int dnsseclame, 246238106Sdes int reclame, uint16_t qtype); 247238106Sdes 248238106Sdes/** 249238106Sdes * Update rtt information for the host. 250238106Sdes * @param infra: infrastructure cache. 251238106Sdes * @param addr: host address. 252238106Sdes * @param addrlen: length of addr. 253238106Sdes * @param name: zone name 254238106Sdes * @param namelen: zone name length 255238106Sdes * @param qtype: query type. 256238106Sdes * @param roundtrip: estimate of roundtrip time in milliseconds or -1 for 257238106Sdes * timeout. 258238106Sdes * @param orig_rtt: original rtt for the query that timed out (roundtrip==-1). 259238106Sdes * ignored if roundtrip != -1. 260238106Sdes * @param timenow: what time it is now. 261238106Sdes * @return: 0 on error. new rto otherwise. 262238106Sdes */ 263238106Sdesint infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr, 264238106Sdes socklen_t addrlen, uint8_t* name, size_t namelen, int qtype, 265269257Sdes int roundtrip, int orig_rtt, time_t timenow); 266238106Sdes 267238106Sdes/** 268238106Sdes * Update information for the host, store that a TCP transaction works. 269238106Sdes * @param infra: infrastructure cache. 270238106Sdes * @param addr: host address. 271238106Sdes * @param addrlen: length of addr. 272238106Sdes * @param name: name of zone 273238106Sdes * @param namelen: length of name 274238106Sdes */ 275238106Sdesvoid infra_update_tcp_works(struct infra_cache* infra, 276238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, 277238106Sdes uint8_t* name, size_t namelen); 278238106Sdes 279238106Sdes/** 280238106Sdes * Update edns information for the host. 281238106Sdes * @param infra: infrastructure cache. 282238106Sdes * @param addr: host address. 283238106Sdes * @param addrlen: length of addr. 284238106Sdes * @param name: name of zone 285238106Sdes * @param namelen: length of name 286238106Sdes * @param edns_version: the version that it publishes. 287238106Sdes * If it is known to support EDNS then no-EDNS is not stored over it. 288238106Sdes * @param timenow: what time it is now. 289238106Sdes * @return: 0 on error. 290238106Sdes */ 291238106Sdesint infra_edns_update(struct infra_cache* infra, 292238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, 293269257Sdes uint8_t* name, size_t namelen, int edns_version, time_t timenow); 294238106Sdes 295238106Sdes/** 296238106Sdes * Get Lameness information and average RTT if host is in the cache. 297238106Sdes * This information is to be used for server selection. 298238106Sdes * @param infra: infrastructure cache. 299238106Sdes * @param addr: host address. 300238106Sdes * @param addrlen: length of addr. 301238106Sdes * @param name: zone name. 302238106Sdes * @param namelen: zone name length. 303238106Sdes * @param qtype: the query to be made. 304238106Sdes * @param lame: if function returns true, this returns lameness of the zone. 305238106Sdes * @param dnsseclame: if function returns true, this returns if the zone 306238106Sdes * is dnssec-lame. 307238106Sdes * @param reclame: if function returns true, this is if it is recursion lame. 308238106Sdes * @param rtt: if function returns true, this returns avg rtt of the server. 309238106Sdes * The rtt value is unclamped and reflects recent timeouts. 310238106Sdes * @param timenow: what time it is now. 311238106Sdes * @return if found in cache, or false if not (or TTL bad). 312238106Sdes */ 313238106Sdesint infra_get_lame_rtt(struct infra_cache* infra, 314238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, 315238106Sdes uint8_t* name, size_t namelen, uint16_t qtype, 316269257Sdes int* lame, int* dnsseclame, int* reclame, int* rtt, time_t timenow); 317238106Sdes 318238106Sdes/** 319238106Sdes * Get additional (debug) info on timing. 320238106Sdes * @param infra: infra cache. 321238106Sdes * @param addr: host address. 322238106Sdes * @param addrlen: length of addr. 323238106Sdes * @param name: zone name 324238106Sdes * @param namelen: zone name length 325238106Sdes * @param rtt: the rtt_info is copied into here (caller alloced return struct). 326238106Sdes * @param delay: probe delay (if any). 327238106Sdes * @param timenow: what time it is now. 328238106Sdes * @param tA: timeout counter on type A. 329238106Sdes * @param tAAAA: timeout counter on type AAAA. 330238106Sdes * @param tother: timeout counter on type other. 331238106Sdes * @return TTL the infra host element is valid for. If -1: not found in cache. 332238106Sdes * TTL -2: found but expired. 333238106Sdes */ 334269257Sdeslong long infra_get_host_rto(struct infra_cache* infra, 335238106Sdes struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, 336269257Sdes size_t namelen, struct rtt_info* rtt, int* delay, time_t timenow, 337238106Sdes int* tA, int* tAAAA, int* tother); 338238106Sdes 339238106Sdes/** 340291767Sdes * Increment the query rate counter for a delegation point. 341291767Sdes * @param infra: infra cache. 342291767Sdes * @param name: zone name 343291767Sdes * @param namelen: zone name length 344291767Sdes * @param timenow: what time it is now. 345291767Sdes * @return 1 if it could be incremented. 0 if the increment overshot the 346291767Sdes * ratelimit or if in the previous second the ratelimit was exceeded. 347291767Sdes * Failures like alloc failures are not returned (probably as 1). 348291767Sdes */ 349291767Sdesint infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name, 350291767Sdes size_t namelen, time_t timenow); 351291767Sdes 352291767Sdes/** 353291767Sdes * Decrement the query rate counter for a delegation point. 354291767Sdes * Because the reply received for the delegation point was pleasant, 355291767Sdes * we do not charge this delegation point with it (i.e. it was a referral). 356291767Sdes * Should call it with same second as when inc() was called. 357291767Sdes * @param infra: infra cache. 358291767Sdes * @param name: zone name 359291767Sdes * @param namelen: zone name length 360291767Sdes * @param timenow: what time it is now. 361291767Sdes */ 362291767Sdesvoid infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name, 363291767Sdes size_t namelen, time_t timenow); 364291767Sdes 365291767Sdes/** 366291767Sdes * See if the query rate counter for a delegation point is exceeded. 367291767Sdes * So, no queries are going to be allowed. 368291767Sdes * @param infra: infra cache. 369291767Sdes * @param name: zone name 370291767Sdes * @param namelen: zone name length 371291767Sdes * @param timenow: what time it is now. 372291767Sdes * @return true if exceeded. 373291767Sdes */ 374291767Sdesint infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name, 375291767Sdes size_t namelen, time_t timenow); 376291767Sdes 377291767Sdes/** find the maximum rate stored, not too old. 0 if no information. */ 378291767Sdesint infra_rate_max(void* data, time_t now); 379291767Sdes 380291767Sdes/** find the ratelimit in qps for a domain */ 381291767Sdesint infra_find_ratelimit(struct infra_cache* infra, uint8_t* name, 382291767Sdes size_t namelen); 383291767Sdes 384291767Sdes/** 385238106Sdes * Get memory used by the infra cache. 386238106Sdes * @param infra: infrastructure cache. 387238106Sdes * @return memory in use in bytes. 388238106Sdes */ 389238106Sdessize_t infra_get_mem(struct infra_cache* infra); 390238106Sdes 391238106Sdes/** calculate size for the hashtable, does not count size of lameness, 392238106Sdes * so the hashtable is a fixed number of items */ 393238106Sdessize_t infra_sizefunc(void* k, void* d); 394238106Sdes 395238106Sdes/** compare two addresses, returns -1, 0, or +1 */ 396238106Sdesint infra_compfunc(void* key1, void* key2); 397238106Sdes 398238106Sdes/** delete key, and destroy the lock */ 399238106Sdesvoid infra_delkeyfunc(void* k, void* arg); 400238106Sdes 401238106Sdes/** delete data and destroy the lameness hashtable */ 402238106Sdesvoid infra_deldatafunc(void* d, void* arg); 403238106Sdes 404291767Sdes/** calculate size for the hashtable */ 405291767Sdessize_t rate_sizefunc(void* k, void* d); 406291767Sdes 407291767Sdes/** compare two names, returns -1, 0, or +1 */ 408291767Sdesint rate_compfunc(void* key1, void* key2); 409291767Sdes 410291767Sdes/** delete key, and destroy the lock */ 411291767Sdesvoid rate_delkeyfunc(void* k, void* arg); 412291767Sdes 413291767Sdes/** delete data */ 414291767Sdesvoid rate_deldatafunc(void* d, void* arg); 415291767Sdes 416238106Sdes#endif /* SERVICES_CACHE_INFRA_H */ 417