1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * validator/val_neg.h - validator aggressive negative caching functions. 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2008, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav 36b7579f77SDag-Erling Smørgrav /** 37b7579f77SDag-Erling Smørgrav * \file 38b7579f77SDag-Erling Smørgrav * 39b7579f77SDag-Erling Smørgrav * This file contains helper functions for the validator module. 40b7579f77SDag-Erling Smørgrav * The functions help with aggressive negative caching. 4105ab2901SDag-Erling Smørgrav * This creates new denials of existence, and proofs for absence of types 42b7579f77SDag-Erling Smørgrav * from cached NSEC records. 43b7579f77SDag-Erling Smørgrav */ 44b7579f77SDag-Erling Smørgrav 45b7579f77SDag-Erling Smørgrav #ifndef VALIDATOR_VAL_NEG_H 46b7579f77SDag-Erling Smørgrav #define VALIDATOR_VAL_NEG_H 47b7579f77SDag-Erling Smørgrav #include "util/locks.h" 48b7579f77SDag-Erling Smørgrav #include "util/rbtree.h" 4917d15b25SDag-Erling Smørgrav struct sldns_buffer; 50b7579f77SDag-Erling Smørgrav struct val_neg_data; 51b7579f77SDag-Erling Smørgrav struct config_file; 52b7579f77SDag-Erling Smørgrav struct reply_info; 53b7579f77SDag-Erling Smørgrav struct rrset_cache; 54b7579f77SDag-Erling Smørgrav struct regional; 55b7579f77SDag-Erling Smørgrav struct query_info; 56b7579f77SDag-Erling Smørgrav struct dns_msg; 57b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key; 58b7579f77SDag-Erling Smørgrav 59b7579f77SDag-Erling Smørgrav /** 60b7579f77SDag-Erling Smørgrav * The negative cache. It is shared between the threads, so locked. 61b7579f77SDag-Erling Smørgrav * Kept as validator-environ-state. It refers back to the rrset cache for 62b7579f77SDag-Erling Smørgrav * data elements. It can be out of date and contain conflicting data 63b7579f77SDag-Erling Smørgrav * from zone content changes. 64b7579f77SDag-Erling Smørgrav * It contains a tree of zones, every zone has a tree of data elements. 65b7579f77SDag-Erling Smørgrav * The data elements are part of one big LRU list, with one memory counter. 66b7579f77SDag-Erling Smørgrav */ 67b7579f77SDag-Erling Smørgrav struct val_neg_cache { 68b7579f77SDag-Erling Smørgrav /** the big lock on the negative cache. Because we use a rbtree 69b7579f77SDag-Erling Smørgrav * for the data (quick lookup), we need a big lock */ 703005e0a3SDag-Erling Smørgrav lock_basic_type lock; 71b7579f77SDag-Erling Smørgrav /** The zone rbtree. contents sorted canonical, type val_neg_zone */ 723005e0a3SDag-Erling Smørgrav rbtree_type tree; 73b7579f77SDag-Erling Smørgrav /** the first in linked list of LRU of val_neg_data */ 74b7579f77SDag-Erling Smørgrav struct val_neg_data* first; 75b7579f77SDag-Erling Smørgrav /** last in lru (least recently used element) */ 76b7579f77SDag-Erling Smørgrav struct val_neg_data* last; 77b7579f77SDag-Erling Smørgrav /** current memory in use (bytes) */ 78b7579f77SDag-Erling Smørgrav size_t use; 79b7579f77SDag-Erling Smørgrav /** max memory to use (bytes) */ 80b7579f77SDag-Erling Smørgrav size_t max; 81b7579f77SDag-Erling Smørgrav /** max nsec3 iterations allowed */ 82b7579f77SDag-Erling Smørgrav size_t nsec3_max_iter; 83*0fb34990SDag-Erling Smørgrav /** number of times neg cache records were used to generate NOERROR 84*0fb34990SDag-Erling Smørgrav * responses. */ 85*0fb34990SDag-Erling Smørgrav size_t num_neg_cache_noerror; 86*0fb34990SDag-Erling Smørgrav /** number of times neg cache records were used to generate NXDOMAIN 87*0fb34990SDag-Erling Smørgrav * responses. */ 88*0fb34990SDag-Erling Smørgrav size_t num_neg_cache_nxdomain; 89b7579f77SDag-Erling Smørgrav }; 90b7579f77SDag-Erling Smørgrav 91b7579f77SDag-Erling Smørgrav /** 92b7579f77SDag-Erling Smørgrav * Per Zone aggressive negative caching data. 93b7579f77SDag-Erling Smørgrav */ 94b7579f77SDag-Erling Smørgrav struct val_neg_zone { 95b7579f77SDag-Erling Smørgrav /** rbtree node element, key is this struct: the name, class */ 963005e0a3SDag-Erling Smørgrav rbnode_type node; 97b7579f77SDag-Erling Smørgrav /** name; the key */ 98b7579f77SDag-Erling Smørgrav uint8_t* name; 99b7579f77SDag-Erling Smørgrav /** length of name */ 100b7579f77SDag-Erling Smørgrav size_t len; 101b7579f77SDag-Erling Smørgrav /** labels in name */ 102b7579f77SDag-Erling Smørgrav int labs; 103b7579f77SDag-Erling Smørgrav 104b7579f77SDag-Erling Smørgrav /** pointer to parent zone in the negative cache */ 105b7579f77SDag-Erling Smørgrav struct val_neg_zone* parent; 106b7579f77SDag-Erling Smørgrav 107b7579f77SDag-Erling Smørgrav /** the number of elements, including this one and the ones whose 108b7579f77SDag-Erling Smørgrav * parents (-parents) include this one, that are in_use 109b7579f77SDag-Erling Smørgrav * No elements have a count of zero, those are removed. */ 110b7579f77SDag-Erling Smørgrav int count; 111b7579f77SDag-Erling Smørgrav 112b7579f77SDag-Erling Smørgrav /** if 0: NSEC zone, else NSEC3 hash algorithm in use */ 113b7579f77SDag-Erling Smørgrav int nsec3_hash; 114b7579f77SDag-Erling Smørgrav /** nsec3 iteration count in use */ 115b7579f77SDag-Erling Smørgrav size_t nsec3_iter; 116b7579f77SDag-Erling Smørgrav /** nsec3 salt in use */ 117b7579f77SDag-Erling Smørgrav uint8_t* nsec3_salt; 118b7579f77SDag-Erling Smørgrav /** length of salt in bytes */ 119b7579f77SDag-Erling Smørgrav size_t nsec3_saltlen; 120b7579f77SDag-Erling Smørgrav 121b7579f77SDag-Erling Smørgrav /** tree of NSEC data for this zone, sorted canonical 122b7579f77SDag-Erling Smørgrav * by NSEC owner name */ 1233005e0a3SDag-Erling Smørgrav rbtree_type tree; 124b7579f77SDag-Erling Smørgrav 125b7579f77SDag-Erling Smørgrav /** class of node; host order */ 126b7579f77SDag-Erling Smørgrav uint16_t dclass; 127b7579f77SDag-Erling Smørgrav /** if this element is in use, boolean */ 128b7579f77SDag-Erling Smørgrav uint8_t in_use; 129b7579f77SDag-Erling Smørgrav }; 130b7579f77SDag-Erling Smørgrav 131b7579f77SDag-Erling Smørgrav /** 132b7579f77SDag-Erling Smørgrav * Data element for aggressive negative caching. 133b7579f77SDag-Erling Smørgrav * The tree of these elements acts as an index onto the rrset cache. 134b7579f77SDag-Erling Smørgrav * It shows the NSEC records that (may) exist and are (possibly) secure. 135b7579f77SDag-Erling Smørgrav * The rbtree allows for logN search for a covering NSEC record. 136b7579f77SDag-Erling Smørgrav * To make tree insertion and deletion logN too, all the parent (one label 137b7579f77SDag-Erling Smørgrav * less than the name) data elements are also in the rbtree, with a usage 138b7579f77SDag-Erling Smørgrav * count for every data element. 139b7579f77SDag-Erling Smørgrav * There is no actual data stored in this data element, if it is in_use, 140b7579f77SDag-Erling Smørgrav * then the data can (possibly) be found in the rrset cache. 141b7579f77SDag-Erling Smørgrav */ 142b7579f77SDag-Erling Smørgrav struct val_neg_data { 143b7579f77SDag-Erling Smørgrav /** rbtree node element, key is this struct: the name */ 1443005e0a3SDag-Erling Smørgrav rbnode_type node; 145b7579f77SDag-Erling Smørgrav /** name; the key */ 146b7579f77SDag-Erling Smørgrav uint8_t* name; 147b7579f77SDag-Erling Smørgrav /** length of name */ 148b7579f77SDag-Erling Smørgrav size_t len; 149b7579f77SDag-Erling Smørgrav /** labels in name */ 150b7579f77SDag-Erling Smørgrav int labs; 151b7579f77SDag-Erling Smørgrav 152b7579f77SDag-Erling Smørgrav /** pointer to parent node in the negative cache */ 153b7579f77SDag-Erling Smørgrav struct val_neg_data* parent; 154b7579f77SDag-Erling Smørgrav 155b7579f77SDag-Erling Smørgrav /** the number of elements, including this one and the ones whose 156b7579f77SDag-Erling Smørgrav * parents (-parents) include this one, that are in use 157b7579f77SDag-Erling Smørgrav * No elements have a count of zero, those are removed. */ 158b7579f77SDag-Erling Smørgrav int count; 159b7579f77SDag-Erling Smørgrav 160b7579f77SDag-Erling Smørgrav /** the zone that this denial is part of */ 161b7579f77SDag-Erling Smørgrav struct val_neg_zone* zone; 162b7579f77SDag-Erling Smørgrav 163b7579f77SDag-Erling Smørgrav /** previous in LRU */ 164b7579f77SDag-Erling Smørgrav struct val_neg_data* prev; 165b7579f77SDag-Erling Smørgrav /** next in LRU (next element was less recently used) */ 166b7579f77SDag-Erling Smørgrav struct val_neg_data* next; 167b7579f77SDag-Erling Smørgrav 168b7579f77SDag-Erling Smørgrav /** if this element is in use, boolean */ 169b7579f77SDag-Erling Smørgrav uint8_t in_use; 170b7579f77SDag-Erling Smørgrav }; 171b7579f77SDag-Erling Smørgrav 172b7579f77SDag-Erling Smørgrav /** 173b7579f77SDag-Erling Smørgrav * Create negative cache 174b7579f77SDag-Erling Smørgrav * @param cfg: config options. 175b7579f77SDag-Erling Smørgrav * @param maxiter: max nsec3 iterations allowed. 176b7579f77SDag-Erling Smørgrav * @return neg cache, empty or NULL on failure. 177b7579f77SDag-Erling Smørgrav */ 178b7579f77SDag-Erling Smørgrav struct val_neg_cache* val_neg_create(struct config_file* cfg, size_t maxiter); 179b7579f77SDag-Erling Smørgrav 180b7579f77SDag-Erling Smørgrav /** 181b7579f77SDag-Erling Smørgrav * see how much memory is in use by the negative cache. 182b7579f77SDag-Erling Smørgrav * @param neg: negative cache 183b7579f77SDag-Erling Smørgrav * @return number of bytes in use. 184b7579f77SDag-Erling Smørgrav */ 185b7579f77SDag-Erling Smørgrav size_t val_neg_get_mem(struct val_neg_cache* neg); 186b7579f77SDag-Erling Smørgrav 187b7579f77SDag-Erling Smørgrav /** 188b7579f77SDag-Erling Smørgrav * Destroy negative cache. There must no longer be any other threads. 189b7579f77SDag-Erling Smørgrav * @param neg: negative cache. 190b7579f77SDag-Erling Smørgrav */ 191b7579f77SDag-Erling Smørgrav void neg_cache_delete(struct val_neg_cache* neg); 192b7579f77SDag-Erling Smørgrav 193b7579f77SDag-Erling Smørgrav /** 194b7579f77SDag-Erling Smørgrav * Comparison function for rbtree val neg data elements 195b7579f77SDag-Erling Smørgrav */ 196b7579f77SDag-Erling Smørgrav int val_neg_data_compare(const void* a, const void* b); 197b7579f77SDag-Erling Smørgrav 198b7579f77SDag-Erling Smørgrav /** 199b7579f77SDag-Erling Smørgrav * Comparison function for rbtree val neg zone elements 200b7579f77SDag-Erling Smørgrav */ 201b7579f77SDag-Erling Smørgrav int val_neg_zone_compare(const void* a, const void* b); 202b7579f77SDag-Erling Smørgrav 203b7579f77SDag-Erling Smørgrav /** 204b7579f77SDag-Erling Smørgrav * Insert NSECs from this message into the negative cache for reference. 205b7579f77SDag-Erling Smørgrav * @param neg: negative cache 206b7579f77SDag-Erling Smørgrav * @param rep: reply with NSECs. 207b7579f77SDag-Erling Smørgrav * Errors are ignored, means that storage is omitted. 208b7579f77SDag-Erling Smørgrav */ 209b7579f77SDag-Erling Smørgrav void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep); 210b7579f77SDag-Erling Smørgrav 211b7579f77SDag-Erling Smørgrav /** 212b7579f77SDag-Erling Smørgrav * Insert NSECs from this referral into the negative cache for reference. 213b7579f77SDag-Erling Smørgrav * @param neg: negative cache 214b7579f77SDag-Erling Smørgrav * @param rep: referral reply with NS, NSECs. 215b7579f77SDag-Erling Smørgrav * @param zone: bailiwick for the referral. 216b7579f77SDag-Erling Smørgrav * Errors are ignored, means that storage is omitted. 217b7579f77SDag-Erling Smørgrav */ 218b7579f77SDag-Erling Smørgrav void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep, 219b7579f77SDag-Erling Smørgrav uint8_t* zone); 220b7579f77SDag-Erling Smørgrav 221b7579f77SDag-Erling Smørgrav /** 222b7579f77SDag-Erling Smørgrav * For the given query, try to get a reply out of the negative cache. 223b7579f77SDag-Erling Smørgrav * The reply still needs to be validated. 224b7579f77SDag-Erling Smørgrav * @param neg: negative cache. 225b7579f77SDag-Erling Smørgrav * @param qinfo: query 226b7579f77SDag-Erling Smørgrav * @param region: where to allocate reply. 227b7579f77SDag-Erling Smørgrav * @param rrset_cache: rrset cache. 228b7579f77SDag-Erling Smørgrav * @param buf: temporary buffer. 229b7579f77SDag-Erling Smørgrav * @param now: to check TTLs against. 230b7579f77SDag-Erling Smørgrav * @param addsoa: if true, produce result for external consumption. 231b7579f77SDag-Erling Smørgrav * if false, do not add SOA - for unbound-internal consumption. 232b7579f77SDag-Erling Smørgrav * @param topname: do not look higher than this name, 233b7579f77SDag-Erling Smørgrav * so that the result cannot be taken from a zone above the current 234b7579f77SDag-Erling Smørgrav * trust anchor. Which could happen with multiple islands of trust. 235b7579f77SDag-Erling Smørgrav * if NULL, then no trust anchor is used, but also the algorithm becomes 236b7579f77SDag-Erling Smørgrav * more conservative, especially for opt-out zones, since the receiver 237b7579f77SDag-Erling Smørgrav * may have a trust-anchor below the optout and thus the optout cannot 238b7579f77SDag-Erling Smørgrav * be used to create a proof from the negative cache. 23957bddd21SDag-Erling Smørgrav * @param cfg: config options. 240b7579f77SDag-Erling Smørgrav * @return a reply message if something was found. 241b7579f77SDag-Erling Smørgrav * This reply may still need validation. 242b7579f77SDag-Erling Smørgrav * NULL if nothing found (or out of memory). 243b7579f77SDag-Erling Smørgrav */ 244b7579f77SDag-Erling Smørgrav struct dns_msg* val_neg_getmsg(struct val_neg_cache* neg, 245b7579f77SDag-Erling Smørgrav struct query_info* qinfo, struct regional* region, 24617d15b25SDag-Erling Smørgrav struct rrset_cache* rrset_cache, struct sldns_buffer* buf, time_t now, 24757bddd21SDag-Erling Smørgrav int addsoa, uint8_t* topname, struct config_file* cfg); 248b7579f77SDag-Erling Smørgrav 249b7579f77SDag-Erling Smørgrav 250b7579f77SDag-Erling Smørgrav /**** functions exposed for unit test ****/ 251b7579f77SDag-Erling Smørgrav /** 252b7579f77SDag-Erling Smørgrav * Insert data into the data tree of a zone 253b7579f77SDag-Erling Smørgrav * Does not do locking. 254b7579f77SDag-Erling Smørgrav * @param neg: negative cache 255b7579f77SDag-Erling Smørgrav * @param zone: zone to insert into 256b7579f77SDag-Erling Smørgrav * @param nsec: record to insert. 257b7579f77SDag-Erling Smørgrav */ 258b7579f77SDag-Erling Smørgrav void neg_insert_data(struct val_neg_cache* neg, 259b7579f77SDag-Erling Smørgrav struct val_neg_zone* zone, struct ub_packed_rrset_key* nsec); 260b7579f77SDag-Erling Smørgrav 261b7579f77SDag-Erling Smørgrav /** 262b7579f77SDag-Erling Smørgrav * Delete a data element from the negative cache. 263b7579f77SDag-Erling Smørgrav * May delete other data elements to keep tree coherent, or 264b7579f77SDag-Erling Smørgrav * only mark the element as 'not in use'. 265b7579f77SDag-Erling Smørgrav * Does not do locking. 266b7579f77SDag-Erling Smørgrav * @param neg: negative cache. 267b7579f77SDag-Erling Smørgrav * @param el: data element to delete. 268b7579f77SDag-Erling Smørgrav */ 269b7579f77SDag-Erling Smørgrav void neg_delete_data(struct val_neg_cache* neg, struct val_neg_data* el); 270b7579f77SDag-Erling Smørgrav 271b7579f77SDag-Erling Smørgrav /** 272b7579f77SDag-Erling Smørgrav * Find the given zone, from the SOA owner name and class 273b7579f77SDag-Erling Smørgrav * Does not do locking. 274b7579f77SDag-Erling Smørgrav * @param neg: negative cache 275b7579f77SDag-Erling Smørgrav * @param nm: what to look for. 276b7579f77SDag-Erling Smørgrav * @param len: length of nm 277b7579f77SDag-Erling Smørgrav * @param dclass: class to look for. 278b7579f77SDag-Erling Smørgrav * @return zone or NULL if not found. 279b7579f77SDag-Erling Smørgrav */ 280b7579f77SDag-Erling Smørgrav struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg, 281b7579f77SDag-Erling Smørgrav uint8_t* nm, size_t len, uint16_t dclass); 282b7579f77SDag-Erling Smørgrav 283b7579f77SDag-Erling Smørgrav /** 284b7579f77SDag-Erling Smørgrav * Create a new zone. 285b7579f77SDag-Erling Smørgrav * Does not do locking. 286b7579f77SDag-Erling Smørgrav * @param neg: negative cache 287b7579f77SDag-Erling Smørgrav * @param nm: what to look for. 288b7579f77SDag-Erling Smørgrav * @param nm_len: length of name. 289b7579f77SDag-Erling Smørgrav * @param dclass: class of zone, host order. 290b7579f77SDag-Erling Smørgrav * @return zone or NULL if out of memory. 291b7579f77SDag-Erling Smørgrav */ 292b7579f77SDag-Erling Smørgrav struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg, 293b7579f77SDag-Erling Smørgrav uint8_t* nm, size_t nm_len, uint16_t dclass); 294b7579f77SDag-Erling Smørgrav 295b7579f77SDag-Erling Smørgrav /** 296b7579f77SDag-Erling Smørgrav * take a zone into use. increases counts of parents. 297b7579f77SDag-Erling Smørgrav * Does not do locking. 298b7579f77SDag-Erling Smørgrav * @param zone: zone to take into use. 299b7579f77SDag-Erling Smørgrav */ 300b7579f77SDag-Erling Smørgrav void val_neg_zone_take_inuse(struct val_neg_zone* zone); 301b7579f77SDag-Erling Smørgrav 302b7579f77SDag-Erling Smørgrav #endif /* VALIDATOR_VAL_NEG_H */ 303